JobsController.java

1
package edu.ucsb.cs156.courses.controllers;
2
3
import com.fasterxml.jackson.core.JsonProcessingException;
4
import com.fasterxml.jackson.databind.ObjectMapper;
5
import edu.ucsb.cs156.courses.collections.ConvertedSectionCollection;
6
import edu.ucsb.cs156.courses.entities.Job;
7
import edu.ucsb.cs156.courses.errors.EntityNotFoundException;
8
import edu.ucsb.cs156.courses.jobs.TestJob;
9
import edu.ucsb.cs156.courses.jobs.UpdateCourseDataJobFactory;
10
import edu.ucsb.cs156.courses.jobs.UploadGradeDataJob;
11
import edu.ucsb.cs156.courses.jobs.UploadGradeDataJobFactory;
12
import edu.ucsb.cs156.courses.repositories.JobsRepository;
13
import edu.ucsb.cs156.courses.services.jobs.JobService;
14
import io.swagger.v3.oas.annotations.Operation;
15
import io.swagger.v3.oas.annotations.Parameter;
16
import io.swagger.v3.oas.annotations.tags.Tag;
17
import java.util.Map;
18
import lombok.extern.slf4j.Slf4j;
19
import org.springframework.beans.factory.annotation.Autowired;
20
import org.springframework.security.access.prepost.PreAuthorize;
21
import org.springframework.web.bind.annotation.DeleteMapping;
22
import org.springframework.web.bind.annotation.GetMapping;
23
import org.springframework.web.bind.annotation.PathVariable;
24
import org.springframework.web.bind.annotation.PostMapping;
25
import org.springframework.web.bind.annotation.RequestMapping;
26
import org.springframework.web.bind.annotation.RequestParam;
27
import org.springframework.web.bind.annotation.RestController;
28
29
@Tag(name = "Jobs")
30
@RequestMapping("/api/jobs")
31
@RestController
32
@Slf4j
33
public class JobsController extends ApiController {
34
  @Autowired private JobsRepository jobsRepository;
35
36
  @Autowired private ConvertedSectionCollection convertedSectionCollection;
37
38
  @Autowired private JobService jobService;
39
40
  @Autowired ObjectMapper mapper;
41
42
  @Autowired UpdateCourseDataJobFactory updateCourseDataJobFactory;
43
44
  @Autowired UploadGradeDataJobFactory updateGradeDataJobFactory;
45
46
  @Operation(summary = "List all jobs")
47
  @PreAuthorize("hasRole('ROLE_ADMIN')")
48
  @GetMapping("/all")
49
  public Iterable<Job> allJobs() {
50
    Iterable<Job> jobs = jobsRepository.findAll();
51 1 1. allJobs : replaced return value with Collections.emptyList for edu/ucsb/cs156/courses/controllers/JobsController::allJobs → KILLED
    return jobs;
52
  }
53
54
  @Operation(summary = "Delete all job records")
55
  @PreAuthorize("hasRole('ROLE_ADMIN')")
56
  @DeleteMapping("/all")
57
  public Map<String, String> deleteAllJobs() {
58 1 1. deleteAllJobs : removed call to edu/ucsb/cs156/courses/repositories/JobsRepository::deleteAll → KILLED
    jobsRepository.deleteAll();
59 1 1. deleteAllJobs : replaced return value with Collections.emptyMap for edu/ucsb/cs156/courses/controllers/JobsController::deleteAllJobs → KILLED
    return Map.of("message", "All jobs deleted");
60
  }
61
62
  @Operation(summary = "Get a specific Job Log by ID if it is in the database")
63
  @PreAuthorize("hasRole('ROLE_ADMIN')")
64
  @GetMapping("")
65
  public Job getJobLogById(
66
      @Parameter(name = "id", description = "ID of the job") @RequestParam Long id)
67
      throws JsonProcessingException {
68
69
    Job job =
70 1 1. lambda$getJobLogById$0 : replaced return value with null for edu/ucsb/cs156/courses/controllers/JobsController::lambda$getJobLogById$0 → KILLED
        jobsRepository.findById(id).orElseThrow(() -> new EntityNotFoundException(Job.class, id));
71
72 1 1. getJobLogById : replaced return value with null for edu/ucsb/cs156/courses/controllers/JobsController::getJobLogById → KILLED
    return job;
73
  }
74
75
  @Operation(summary = "Delete specific job record")
76
  @PreAuthorize("hasRole('ROLE_ADMIN')")
77
  @DeleteMapping("")
78
  public Map<String, String> deleteAllJobs(@Parameter(name = "id") @RequestParam Long id) {
79 1 1. deleteAllJobs : negated conditional → KILLED
    if (!jobsRepository.existsById(id)) {
80 1 1. deleteAllJobs : replaced return value with Collections.emptyMap for edu/ucsb/cs156/courses/controllers/JobsController::deleteAllJobs → KILLED
      return Map.of("message", String.format("Job with id %d not found", id));
81
    }
82 1 1. deleteAllJobs : removed call to edu/ucsb/cs156/courses/repositories/JobsRepository::deleteById → KILLED
    jobsRepository.deleteById(id);
83 1 1. deleteAllJobs : replaced return value with Collections.emptyMap for edu/ucsb/cs156/courses/controllers/JobsController::deleteAllJobs → KILLED
    return Map.of("message", String.format("Job with id %d deleted", id));
84
  }
85
86
  @Operation(summary = "Launch Test Job (click fail if you want to test exception handling)")
87
  @PreAuthorize("hasRole('ROLE_ADMIN')")
88
  @PostMapping("/launch/testjob")
89
  public Job launchTestJob(
90
      @Parameter(name = "fail") @RequestParam Boolean fail,
91
      @Parameter(name = "sleepMs") @RequestParam Integer sleepMs) {
92
93
    TestJob testJob = TestJob.builder().fail(fail).sleepMs(sleepMs).build();
94 1 1. launchTestJob : replaced return value with null for edu/ucsb/cs156/courses/controllers/JobsController::launchTestJob → KILLED
    return jobService.runAsJob(testJob);
95
  }
96
97
  @Operation(summary = "Launch Job to Update Course Data")
98
  @PreAuthorize("hasRole('ROLE_ADMIN')")
99
  @PostMapping("/launch/updateCourses")
100
  public Job launchUpdateCourseDataJob(
101
      @Parameter(name = "quarterYYYYQ", description = "quarter (YYYYQ format)") @RequestParam
102
          String quarterYYYYQ,
103
      @Parameter(name = "subjectArea") @RequestParam String subjectArea,
104
      @Parameter(
105
              name = "ifStale",
106
              description = "true if job should only update when data is stale")
107
          @RequestParam(defaultValue = "true")
108
          Boolean ifStale) {
109
110
    log.info(
111
        "launchUpdateCourseDataJob: quarterYYYYQ={}, subjectArea={}, ifStale={}",
112
        quarterYYYYQ,
113
        subjectArea,
114
        ifStale);
115
    var job =
116
        updateCourseDataJobFactory.createForSubjectAndQuarterAndIfStale(
117
            subjectArea, quarterYYYYQ, ifStale);
118
119 1 1. launchUpdateCourseDataJob : replaced return value with null for edu/ucsb/cs156/courses/controllers/JobsController::launchUpdateCourseDataJob → KILLED
    return jobService.runAsJob(job);
120
  }
121
122
  @Operation(summary = "Launch Job to Update Course Data using Quarter")
123
  @PreAuthorize("hasRole('ROLE_ADMIN')")
124
  @PostMapping("/launch/updateQuarterCourses")
125
  public Job launchUpdateCourseDataWithQuarterJob(
126
      @Parameter(name = "quarterYYYYQ", description = "quarter (YYYYQ format)") @RequestParam
127
          String quarterYYYYQ,
128
      @Parameter(
129
              name = "ifStale",
130
              description = "true if job should only update when data is stale")
131
          @RequestParam(defaultValue = "true")
132
          Boolean ifStale) {
133
134
    var job = updateCourseDataJobFactory.createForQuarter(quarterYYYYQ);
135
136 1 1. launchUpdateCourseDataWithQuarterJob : replaced return value with null for edu/ucsb/cs156/courses/controllers/JobsController::launchUpdateCourseDataWithQuarterJob → KILLED
    return jobService.runAsJob(job);
137
  }
138
139
  @Operation(summary = "Get long job logs")
140
  @PreAuthorize("hasRole('ROLE_ADMIN')")
141
  @GetMapping("/logs/{id}")
142
  public String getJobLogs(@Parameter(name = "id", description = "Job ID") @PathVariable Long id) {
143
144 1 1. getJobLogs : replaced return value with "" for edu/ucsb/cs156/courses/controllers/JobsController::getJobLogs → KILLED
    return jobService.getLongJob(id);
145
  }
146
147
  @Operation(summary = "Launch Job to Update Course Data for range of quarters")
148
  @PreAuthorize("hasRole('ROLE_ADMIN')")
149
  @PostMapping("/launch/updateCoursesRangeOfQuarters")
150
  public Job launchUpdateCourseDataRangeOfQuartersJob(
151
      @Parameter(name = "start_quarterYYYYQ", description = "start quarter (YYYYQ format)")
152
          @RequestParam
153
          String start_quarterYYYYQ,
154
      @Parameter(name = "end_quarterYYYYQ", description = "end quarter (YYYYQ format)")
155
          @RequestParam
156
          String end_quarterYYYYQ,
157
      @Parameter(
158
              name = "ifStale",
159
              description = "true if job should only update when data is stale")
160
          @RequestParam(defaultValue = "true")
161
          Boolean ifStale) {
162
163
    var job =
164
        updateCourseDataJobFactory.createForQuarterRange(start_quarterYYYYQ, end_quarterYYYYQ);
165
166 1 1. launchUpdateCourseDataRangeOfQuartersJob : replaced return value with null for edu/ucsb/cs156/courses/controllers/JobsController::launchUpdateCourseDataRangeOfQuartersJob → KILLED
    return jobService.runAsJob(job);
167
  }
168
169
  @Operation(
170
      summary = "Launch Job to Update Course Data for a range of quarters for a single subject")
171
  @PreAuthorize("hasRole('ROLE_ADMIN')")
172
  @PostMapping("/launch/updateCoursesRangeOfQuartersSingleSubject")
173
  public Job launchUpdateCourseDataRangeOfQuartersSingleSubjectJob(
174
      @Parameter(name = "subjectArea", description = "subject area") @RequestParam
175
          String subjectArea,
176
      @Parameter(name = "start_quarterYYYYQ", description = "start quarter (YYYYQ format)")
177
          @RequestParam
178
          String start_quarterYYYYQ,
179
      @Parameter(name = "end_quarterYYYYQ", description = "end quarter (YYYYQ format)")
180
          @RequestParam
181
          String end_quarterYYYYQ,
182
      @Parameter(
183
              name = "ifStale",
184
              description = "true if job should only update when data is stale")
185
          @RequestParam(defaultValue = "true")
186
          Boolean ifStale) {
187
188
    var job =
189
        updateCourseDataJobFactory.createForSubjectAndQuarterRange(
190
            subjectArea, start_quarterYYYYQ, end_quarterYYYYQ);
191
192 1 1. launchUpdateCourseDataRangeOfQuartersSingleSubjectJob : replaced return value with null for edu/ucsb/cs156/courses/controllers/JobsController::launchUpdateCourseDataRangeOfQuartersSingleSubjectJob → KILLED
    return jobService.runAsJob(job);
193
  }
194
195
  @Operation(summary = "Launch Job to update grade history")
196
  @PreAuthorize("hasRole('ROLE_ADMIN')")
197
  @PostMapping("/launch/uploadGradeData")
198
  public Job launchUploadGradeData() {
199
    UploadGradeDataJob updateGradeDataJob = updateGradeDataJobFactory.create();
200 1 1. launchUploadGradeData : replaced return value with null for edu/ucsb/cs156/courses/controllers/JobsController::launchUploadGradeData → KILLED
    return jobService.runAsJob(updateGradeDataJob);
201
  }
202
}

Mutations

51

1.1
Location : allJobs
Killed by : edu.ucsb.cs156.courses.controllers.JobsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.controllers.JobsControllerTests]/[method:admin_can_get_all_jobs()]
replaced return value with Collections.emptyList for edu/ucsb/cs156/courses/controllers/JobsController::allJobs → KILLED

58

1.1
Location : deleteAllJobs
Killed by : edu.ucsb.cs156.courses.controllers.JobsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.controllers.JobsControllerTests]/[method:admin_can_delete_all_jobs()]
removed call to edu/ucsb/cs156/courses/repositories/JobsRepository::deleteAll → KILLED

59

1.1
Location : deleteAllJobs
Killed by : edu.ucsb.cs156.courses.controllers.JobsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.controllers.JobsControllerTests]/[method:admin_can_delete_all_jobs()]
replaced return value with Collections.emptyMap for edu/ucsb/cs156/courses/controllers/JobsController::deleteAllJobs → KILLED

70

1.1
Location : lambda$getJobLogById$0
Killed by : edu.ucsb.cs156.courses.controllers.JobsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.controllers.JobsControllerTests]/[method:api_getJobLogById__admin_logged_in__returns_not_found_for_missing_job()]
replaced return value with null for edu/ucsb/cs156/courses/controllers/JobsController::lambda$getJobLogById$0 → KILLED

72

1.1
Location : getJobLogById
Killed by : edu.ucsb.cs156.courses.controllers.JobsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.controllers.JobsControllerTests]/[method:api_getJobLogById__admin_logged_in__returns_job_by_id()]
replaced return value with null for edu/ucsb/cs156/courses/controllers/JobsController::getJobLogById → KILLED

79

1.1
Location : deleteAllJobs
Killed by : edu.ucsb.cs156.courses.controllers.JobsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.controllers.JobsControllerTests]/[method:admin_gets_reasonable_error_when_deleting_non_existing_job()]
negated conditional → KILLED

80

1.1
Location : deleteAllJobs
Killed by : edu.ucsb.cs156.courses.controllers.JobsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.controllers.JobsControllerTests]/[method:admin_gets_reasonable_error_when_deleting_non_existing_job()]
replaced return value with Collections.emptyMap for edu/ucsb/cs156/courses/controllers/JobsController::deleteAllJobs → KILLED

82

1.1
Location : deleteAllJobs
Killed by : edu.ucsb.cs156.courses.controllers.JobsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.controllers.JobsControllerTests]/[method:admin_can_delete_specific_job()]
removed call to edu/ucsb/cs156/courses/repositories/JobsRepository::deleteById → KILLED

83

1.1
Location : deleteAllJobs
Killed by : edu.ucsb.cs156.courses.controllers.JobsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.controllers.JobsControllerTests]/[method:admin_can_delete_specific_job()]
replaced return value with Collections.emptyMap for edu/ucsb/cs156/courses/controllers/JobsController::deleteAllJobs → KILLED

94

1.1
Location : launchTestJob
Killed by : edu.ucsb.cs156.courses.controllers.JobsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.controllers.JobsControllerTests]/[method:admin_can_launch_test_job()]
replaced return value with null for edu/ucsb/cs156/courses/controllers/JobsController::launchTestJob → KILLED

119

1.1
Location : launchUpdateCourseDataJob
Killed by : edu.ucsb.cs156.courses.controllers.JobsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.controllers.JobsControllerTests]/[method:admin_can_launch_update_courses_job()]
replaced return value with null for edu/ucsb/cs156/courses/controllers/JobsController::launchUpdateCourseDataJob → KILLED

136

1.1
Location : launchUpdateCourseDataWithQuarterJob
Killed by : edu.ucsb.cs156.courses.controllers.JobsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.controllers.JobsControllerTests]/[method:admin_can_launch_update_courses_job_with_quarter()]
replaced return value with null for edu/ucsb/cs156/courses/controllers/JobsController::launchUpdateCourseDataWithQuarterJob → KILLED

144

1.1
Location : getJobLogs
Killed by : edu.ucsb.cs156.courses.controllers.JobsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.controllers.JobsControllerTests]/[method:test_getJobLogs_admin_can_get_job_log()]
replaced return value with "" for edu/ucsb/cs156/courses/controllers/JobsController::getJobLogs → KILLED

166

1.1
Location : launchUpdateCourseDataRangeOfQuartersJob
Killed by : edu.ucsb.cs156.courses.controllers.JobsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.controllers.JobsControllerTests]/[method:admin_can_launch_update_courses_range_of_quarters_job()]
replaced return value with null for edu/ucsb/cs156/courses/controllers/JobsController::launchUpdateCourseDataRangeOfQuartersJob → KILLED

192

1.1
Location : launchUpdateCourseDataRangeOfQuartersSingleSubjectJob
Killed by : edu.ucsb.cs156.courses.controllers.JobsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.controllers.JobsControllerTests]/[method:admin_can_launch_update_courses_range_of_quarters_single_subject_job()]
replaced return value with null for edu/ucsb/cs156/courses/controllers/JobsController::launchUpdateCourseDataRangeOfQuartersSingleSubjectJob → KILLED

200

1.1
Location : launchUploadGradeData
Killed by : edu.ucsb.cs156.courses.controllers.JobsControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.courses.controllers.JobsControllerTests]/[method:admin_can_launch_upload_course_grade_data_job()]
replaced return value with null for edu/ucsb/cs156/courses/controllers/JobsController::launchUploadGradeData → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0