RosterStudentsCSVController.java

1
package edu.ucsb.cs156.frontiers.controllers;
2
3
import com.fasterxml.jackson.core.JsonProcessingException;
4
import com.opencsv.CSVReader;
5
import com.opencsv.exceptions.CsvException;
6
import edu.ucsb.cs156.frontiers.entities.Course;
7
import edu.ucsb.cs156.frontiers.entities.RosterStudent;
8
import edu.ucsb.cs156.frontiers.enums.InsertStatus;
9
import edu.ucsb.cs156.frontiers.enums.RosterStatus;
10
import edu.ucsb.cs156.frontiers.errors.EntityNotFoundException;
11
import edu.ucsb.cs156.frontiers.jobs.RemoveStudentsJob;
12
import edu.ucsb.cs156.frontiers.models.LoadResult;
13
import edu.ucsb.cs156.frontiers.models.UpsertResponse;
14
import edu.ucsb.cs156.frontiers.repositories.CourseRepository;
15
import edu.ucsb.cs156.frontiers.repositories.RosterStudentRepository;
16
import edu.ucsb.cs156.frontiers.services.OrganizationMemberService;
17
import edu.ucsb.cs156.frontiers.services.UpdateUserService;
18
import edu.ucsb.cs156.frontiers.services.jobs.JobService;
19
import io.swagger.v3.oas.annotations.Operation;
20
import io.swagger.v3.oas.annotations.Parameter;
21
import io.swagger.v3.oas.annotations.tags.Tag;
22
import java.io.BufferedInputStream;
23
import java.io.IOException;
24
import java.io.InputStream;
25
import java.io.InputStreamReader;
26
import java.util.ArrayList;
27
import java.util.Arrays;
28
import java.util.HashMap;
29
import java.util.List;
30
import java.util.Map;
31
import lombok.extern.slf4j.Slf4j;
32
import org.springframework.beans.factory.annotation.Autowired;
33
import org.springframework.http.HttpStatus;
34
import org.springframework.http.ResponseEntity;
35
import org.springframework.security.access.prepost.PreAuthorize;
36
import org.springframework.web.bind.annotation.PostMapping;
37
import org.springframework.web.bind.annotation.RequestMapping;
38
import org.springframework.web.bind.annotation.RequestParam;
39
import org.springframework.web.bind.annotation.RestController;
40
import org.springframework.web.multipart.MultipartFile;
41
import org.springframework.web.server.ResponseStatusException;
42
43
@Tag(name = "RosterStudents")
44
@RequestMapping("/api/rosterstudents")
45
@RestController
46
@Slf4j
47
public class RosterStudentsCSVController extends ApiController {
48
49
  @Autowired private RosterStudentRepository rosterStudentRepository;
50
51
  @Autowired private CourseRepository courseRepository;
52
53
  @Autowired private UpdateUserService updateUserService;
54
  @Autowired private OrganizationMemberService organizationMemberService;
55
  @Autowired private JobService jobService;
56
57
  public enum RosterSourceType {
58
    UCSB_EGRADES,
59
    CHICO_CANVAS,
60
    OREGON_STATE,
61
    UNKNOWN
62
  }
63
64
  public static final String UCSB_EGRADES_HEADERS =
65
      "Enrl Cd,Perm #,Grade,Final Units,Student Last,Student First Middle,Quarter,Course ID,Section,Meeting Time(s) / Location(s),Email,ClassLevel,Major1,Major2,Date/Time,Pronoun";
66
  public static final String CHICO_CANVAS_HEADERS =
67
      "Student Name,Student ID,Student SIS ID,Email,Section Name";
68
  public static final String OREGON_STATE_HEADERS =
69
      "Full name,Sortable name,Canvas user id,Overall course grade,Assignment on time percent,Last page view time,Last participation time,Last logged out,Email,SIS Id";
70
71
  public static RosterSourceType getRosterSourceType(String[] headers) {
72
73
    Map<RosterSourceType, String[]> sourceTypeToHeaders = new HashMap<>();
74
75
    sourceTypeToHeaders.put(RosterSourceType.UCSB_EGRADES, UCSB_EGRADES_HEADERS.split(","));
76
    sourceTypeToHeaders.put(RosterSourceType.CHICO_CANVAS, CHICO_CANVAS_HEADERS.split(","));
77
    sourceTypeToHeaders.put(RosterSourceType.OREGON_STATE, OREGON_STATE_HEADERS.split(","));
78
79
    for (Map.Entry<RosterSourceType, String[]> entry : sourceTypeToHeaders.entrySet()) {
80
      RosterSourceType type = entry.getKey();
81
      String[] expectedHeaders = entry.getValue();
82 2 1. getRosterSourceType : negated conditional → KILLED
2. getRosterSourceType : changed conditional boundary → KILLED
      if (headers.length >= expectedHeaders.length) {
83
        boolean matches = true;
84 2 1. getRosterSourceType : changed conditional boundary → KILLED
2. getRosterSourceType : negated conditional → KILLED
        for (int i = 0; i < expectedHeaders.length; i++) {
85 1 1. getRosterSourceType : negated conditional → KILLED
          if (!expectedHeaders[i].trim().equalsIgnoreCase(headers[i].trim())) {
86
            matches = false;
87
            break;
88
          }
89
        }
90 1 1. getRosterSourceType : negated conditional → KILLED
        if (matches) {
91 1 1. getRosterSourceType : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::getRosterSourceType → KILLED
          return type;
92
        }
93
      }
94
    }
95
    // If no known type matches, return UNKNOWN
96 1 1. getRosterSourceType : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::getRosterSourceType → KILLED
    return RosterSourceType.UNKNOWN;
97
  }
98
99
  /**
100
   * Upload Roster students for Course in any supported format. It is important to keep the code in
101
   * this method consistent with the code for adding a single roster student
102
   *
103
   * @param courseId
104
   * @param file
105
   * @return
106
   * @throws JsonProcessingException
107
   * @throws IOException
108
   * @throws CsvException
109
   */
110
  @Operation(summary = "Upload Roster students for Course in any supported Format")
111
  @PreAuthorize("@CourseSecurity.hasManagePermissions(#root, #courseId)")
112
  @PostMapping(
113
      value = "/upload/csv",
114
      consumes = {"multipart/form-data"})
115
  public ResponseEntity<LoadResult> uploadRosterStudentsCSV(
116
      @Parameter(name = "courseId") @RequestParam Long courseId,
117
      @Parameter(name = "file") @RequestParam("file") MultipartFile file)
118
      throws JsonProcessingException, IOException, CsvException {
119
120
    Course course =
121
        courseRepository
122
            .findById(courseId)
123 1 1. lambda$uploadRosterStudentsCSV$0 : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::lambda$uploadRosterStudentsCSV$0 → KILLED
            .orElseThrow(() -> new EntityNotFoundException(Course.class, courseId.toString()));
124
125
    course.getRosterStudents().stream()
126 2 1. lambda$uploadRosterStudentsCSV$1 : negated conditional → KILLED
2. lambda$uploadRosterStudentsCSV$1 : replaced boolean return with true for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::lambda$uploadRosterStudentsCSV$1 → KILLED
        .filter(filteredStudent -> filteredStudent.getRosterStatus() == RosterStatus.ROSTER)
127 2 1. lambda$uploadRosterStudentsCSV$2 : removed call to edu/ucsb/cs156/frontiers/entities/RosterStudent::setRosterStatus → KILLED
2. uploadRosterStudentsCSV : removed call to java/util/stream/Stream::forEach → KILLED
        .forEach(student -> student.setRosterStatus(RosterStatus.DROPPED));
128
129
    int counts[] = {0, 0};
130
    List<RosterStudent> rejectedStudents = new ArrayList<>();
131
132
    try (InputStream inputStream = new BufferedInputStream(file.getInputStream());
133
        InputStreamReader reader = new InputStreamReader(inputStream);
134
        CSVReader csvReader = new CSVReader(reader); ) {
135
136
      String[] headers = csvReader.readNext();
137
      RosterSourceType sourceType = getRosterSourceType(headers);
138 1 1. uploadRosterStudentsCSV : negated conditional → KILLED
      if (sourceType == RosterSourceType.UNKNOWN) {
139
        throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Unknown Roster Source Type");
140
      }
141 1 1. uploadRosterStudentsCSV : negated conditional → KILLED
      if (sourceType == RosterSourceType.UCSB_EGRADES) {
142 1 1. uploadRosterStudentsCSV : removed call to com/opencsv/CSVReader::skip → KILLED
        csvReader.skip(1);
143
      }
144
      List<String[]> myEntries = csvReader.readAll();
145
      for (String[] row : myEntries) {
146
        RosterStudent rosterStudent = fromCSVRow(row, sourceType);
147
        UpsertResponse upsertResponse =
148
            RosterStudentsController.upsertStudent(rosterStudent, course, RosterStatus.ROSTER);
149 1 1. uploadRosterStudentsCSV : negated conditional → KILLED
        if (upsertResponse.getInsertStatus() == InsertStatus.REJECTED) {
150
          rejectedStudents.add(upsertResponse.rosterStudent());
151
        } else {
152
          InsertStatus s = upsertResponse.getInsertStatus();
153 1 1. uploadRosterStudentsCSV : negated conditional → KILLED
          if (s == InsertStatus.INSERTED) {
154
            course.getRosterStudents().add(upsertResponse.rosterStudent());
155
          }
156 1 1. uploadRosterStudentsCSV : Replaced integer addition with subtraction → KILLED
          counts[s.ordinal()]++;
157
        }
158
      }
159
    }
160 1 1. uploadRosterStudentsCSV : negated conditional → KILLED
    if (rejectedStudents.isEmpty()) {
161
      List<RosterStudent> droppedStudents =
162
          course.getRosterStudents().stream()
163 2 1. lambda$uploadRosterStudentsCSV$3 : replaced boolean return with true for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::lambda$uploadRosterStudentsCSV$3 → KILLED
2. lambda$uploadRosterStudentsCSV$3 : negated conditional → KILLED
              .filter(student -> student.getRosterStatus() == RosterStatus.DROPPED)
164
              .toList();
165
      LoadResult successfulResult =
166
          new LoadResult(
167
              counts[InsertStatus.INSERTED.ordinal()],
168
              counts[InsertStatus.UPDATED.ordinal()],
169
              droppedStudents.size(),
170
              List.of());
171
      rosterStudentRepository.saveAll(course.getRosterStudents());
172 1 1. uploadRosterStudentsCSV : removed call to edu/ucsb/cs156/frontiers/services/UpdateUserService::attachUsersToRosterStudents → KILLED
      updateUserService.attachUsersToRosterStudents(course.getRosterStudents());
173
      RemoveStudentsJob job =
174
          RemoveStudentsJob.builder()
175
              .students(droppedStudents)
176
              .organizationMemberService(organizationMemberService)
177
              .rosterStudentRepository(rosterStudentRepository)
178
              .build();
179
      jobService.runAsJob(job);
180 1 1. uploadRosterStudentsCSV : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::uploadRosterStudentsCSV → KILLED
      return ResponseEntity.ok(successfulResult);
181
    } else {
182
      LoadResult conflictResult = new LoadResult(0, 0, 0, rejectedStudents);
183 1 1. uploadRosterStudentsCSV : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::uploadRosterStudentsCSV → KILLED
      return ResponseEntity.status(HttpStatus.CONFLICT).body(conflictResult);
184
    }
185
  }
186
187
  public static RosterStudent fromCSVRow(String[] row, RosterSourceType sourceType) {
188 1 1. fromCSVRow : negated conditional → KILLED
    if (sourceType == RosterSourceType.UCSB_EGRADES) {
189 1 1. fromCSVRow : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromCSVRow → KILLED
      return fromUCSBEgradesCSVRow(row);
190 1 1. fromCSVRow : negated conditional → KILLED
    } else if (sourceType == RosterSourceType.CHICO_CANVAS) {
191 1 1. fromCSVRow : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromCSVRow → KILLED
      return fromChicoCanvasCSVRow(row);
192 1 1. fromCSVRow : negated conditional → KILLED
    } else if (sourceType == RosterSourceType.OREGON_STATE) {
193 1 1. fromCSVRow : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromCSVRow → KILLED
      return fromOregonStateCSVRow(row);
194
    } else {
195
      throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "CSV format not recognized");
196
    }
197
  }
198
199
  public static void checkRowLength(String[] row, int expectedLength, RosterSourceType sourceType) {
200 2 1. checkRowLength : changed conditional boundary → KILLED
2. checkRowLength : negated conditional → KILLED
    if (row.length < expectedLength) {
201
      throw new ResponseStatusException(
202
          HttpStatus.BAD_REQUEST,
203
          String.format(
204
              "%s CSV row does not have enough columns. Length = %d Row content = [%s]",
205
              sourceType.toString(), row.length, Arrays.toString(row)));
206
    }
207
  }
208
209
  public static RosterStudent fromUCSBEgradesCSVRow(String[] row) {
210 1 1. fromUCSBEgradesCSVRow : removed call to edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::checkRowLength → KILLED
    checkRowLength(row, 11, RosterSourceType.UCSB_EGRADES);
211 1 1. fromUCSBEgradesCSVRow : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromUCSBEgradesCSVRow → KILLED
    return RosterStudent.builder()
212
        .firstName(row[5])
213
        .lastName(row[4])
214
        .studentId(row[1])
215
        .email(row[10])
216
        .section(row[0])
217
        .build();
218
  }
219
220
  public static RosterStudent fromChicoCanvasCSVRow(String[] row) {
221 1 1. fromChicoCanvasCSVRow : removed call to edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::checkRowLength → KILLED
    checkRowLength(row, 4, RosterSourceType.CHICO_CANVAS);
222 1 1. fromChicoCanvasCSVRow : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromChicoCanvasCSVRow → KILLED
    return RosterStudent.builder()
223
        .firstName(getFirstName(row[0]))
224
        .lastName(getLastName(row[0]))
225
        .studentId(row[2])
226
        .email(row[3])
227
        .section("")
228
        .build();
229
  }
230
231
  public static RosterStudent fromOregonStateCSVRow(String[] row) {
232
233 1 1. fromOregonStateCSVRow : removed call to edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::checkRowLength → KILLED
    checkRowLength(row, 10, RosterSourceType.OREGON_STATE);
234
    String sortableName = row[1];
235
    String sortableNameParts[] = sortableName.split(",");
236
    String lastName = sortableNameParts[0].trim();
237 2 1. fromOregonStateCSVRow : changed conditional boundary → KILLED
2. fromOregonStateCSVRow : negated conditional → KILLED
    String firstName = sortableNameParts.length > 1 ? sortableNameParts[1].trim() : "";
238 1 1. fromOregonStateCSVRow : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromOregonStateCSVRow → KILLED
    return RosterStudent.builder()
239
        .firstName(firstName)
240
        .lastName(lastName)
241
        .studentId(row[9])
242
        .email(row[8])
243
        .section("")
244
        .build();
245
  }
246
247
  /**
248
   * Get everything except up to and not including the last space in the full name. If the string
249
   * contains no spaces, return an empty string.
250
   *
251
   * @param fullName
252
   * @return
253
   */
254
  public static String getFirstName(String fullName) {
255
    int lastSpaceIndex = fullName.lastIndexOf(" ");
256 1 1. getFirstName : negated conditional → KILLED
    if (lastSpaceIndex == -1) {
257
      return ""; // No spaces found, return empty string
258
    }
259 1 1. getFirstName : replaced return value with "" for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::getFirstName → KILLED
    return fullName.substring(0, lastSpaceIndex).trim(); // Return everything before the last space
260
  }
261
262
  /**
263
   * Get everything after the last space in the full name. If the string contains no spaces, return
264
   * the entire input string as the result.
265
   *
266
   * @param fullName
267
   * @return best estimate of last name
268
   */
269
  public static String getLastName(String fullName) {
270
    int lastSpaceIndex = fullName.lastIndexOf(" ");
271 1 1. getLastName : negated conditional → KILLED
    if (lastSpaceIndex == -1) {
272 1 1. getLastName : replaced return value with "" for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::getLastName → KILLED
      return fullName; // No spaces found, return the entire string
273
    }
274 2 1. getLastName : Replaced integer addition with subtraction → KILLED
2. getLastName : replaced return value with "" for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::getLastName → KILLED
    return fullName.substring(lastSpaceIndex + 1).trim(); // Return everything after the last space
275
  }
276
}

Mutations

82

1.1
Location : getRosterSourceType
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_getRosterSourceType()]
negated conditional → KILLED

2.2
Location : getRosterSourceType
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_getRosterSourceType()]
changed conditional boundary → KILLED

84

1.1
Location : getRosterSourceType
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_getRosterSourceType()]
changed conditional boundary → KILLED

2.2
Location : getRosterSourceType
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_getRosterSourceType()]
negated conditional → KILLED

85

1.1
Location : getRosterSourceType
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_getRosterSourceType()]
negated conditional → KILLED

90

1.1
Location : getRosterSourceType
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_getRosterSourceType()]
negated conditional → KILLED

91

1.1
Location : getRosterSourceType
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_getRosterSourceType()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::getRosterSourceType → KILLED

96

1.1
Location : getRosterSourceType
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_getRosterSourceType()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::getRosterSourceType → KILLED

123

1.1
Location : lambda$uploadRosterStudentsCSV$0
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:instructor_cannot_upload_students_for_a_course_that_does_not_exist()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::lambda$uploadRosterStudentsCSV$0 → KILLED

126

1.1
Location : lambda$uploadRosterStudentsCSV$1
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:drops_handled_correctly()]
negated conditional → KILLED

2.2
Location : lambda$uploadRosterStudentsCSV$1
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:drops_handled_correctly()]
replaced boolean return with true for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::lambda$uploadRosterStudentsCSV$1 → KILLED

127

1.1
Location : lambda$uploadRosterStudentsCSV$2
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:drops_handled_correctly()]
removed call to edu/ucsb/cs156/frontiers/entities/RosterStudent::setRosterStatus → KILLED

2.2
Location : uploadRosterStudentsCSV
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:drops_handled_correctly()]
removed call to java/util/stream/Stream::forEach → KILLED

138

1.1
Location : uploadRosterStudentsCSV
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:unrecognized_csv_format_throws_an_exception()]
negated conditional → KILLED

141

1.1
Location : uploadRosterStudentsCSV
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:drops_handled_correctly()]
negated conditional → KILLED

142

1.1
Location : uploadRosterStudentsCSV
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:drops_handled_correctly()]
removed call to com/opencsv/CSVReader::skip → KILLED

149

1.1
Location : uploadRosterStudentsCSV
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:drops_handled_correctly()]
negated conditional → KILLED

153

1.1
Location : uploadRosterStudentsCSV
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:instructor_can_upload_students_for_an_existing_course_chico()]
negated conditional → KILLED

156

1.1
Location : uploadRosterStudentsCSV
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:drops_handled_correctly()]
Replaced integer addition with subtraction → KILLED

160

1.1
Location : uploadRosterStudentsCSV
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:drops_handled_correctly()]
negated conditional → KILLED

163

1.1
Location : lambda$uploadRosterStudentsCSV$3
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:drops_handled_correctly()]
replaced boolean return with true for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::lambda$uploadRosterStudentsCSV$3 → KILLED

2.2
Location : lambda$uploadRosterStudentsCSV$3
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:drops_handled_correctly()]
negated conditional → KILLED

172

1.1
Location : uploadRosterStudentsCSV
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:instructor_can_upload_students_for_an_existing_course_chico()]
removed call to edu/ucsb/cs156/frontiers/services/UpdateUserService::attachUsersToRosterStudents → KILLED

180

1.1
Location : uploadRosterStudentsCSV
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:drops_handled_correctly()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::uploadRosterStudentsCSV → KILLED

183

1.1
Location : uploadRosterStudentsCSV
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:students_with_non_matching_student_id_and_email_are_rejected()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::uploadRosterStudentsCSV → KILLED

188

1.1
Location : fromCSVRow
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowOregonState_notEnoughColumns()]
negated conditional → KILLED

189

1.1
Location : fromCSVRow
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowUCSB_sectionField()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromCSVRow → KILLED

190

1.1
Location : fromCSVRow
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowOregonState_notEnoughColumns()]
negated conditional → KILLED

191

1.1
Location : fromCSVRow
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowChico_sectionField()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromCSVRow → KILLED

192

1.1
Location : fromCSVRow
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowOregonState_notEnoughColumns()]
negated conditional → KILLED

193

1.1
Location : fromCSVRow
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowOregonState()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromCSVRow → KILLED

200

1.1
Location : checkRowLength
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowOregonState()]
changed conditional boundary → KILLED

2.2
Location : checkRowLength
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowOregonState_notEnoughColumns()]
negated conditional → KILLED

210

1.1
Location : fromUCSBEgradesCSVRow
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowUCSB_notEnoughColumns()]
removed call to edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::checkRowLength → KILLED

211

1.1
Location : fromUCSBEgradesCSVRow
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowUCSB_sectionField()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromUCSBEgradesCSVRow → KILLED

221

1.1
Location : fromChicoCanvasCSVRow
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowChico_notEnoughColumns()]
removed call to edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::checkRowLength → KILLED

222

1.1
Location : fromChicoCanvasCSVRow
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowChico_sectionField()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromChicoCanvasCSVRow → KILLED

233

1.1
Location : fromOregonStateCSVRow
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowOregonState_notEnoughColumns()]
removed call to edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::checkRowLength → KILLED

237

1.1
Location : fromOregonStateCSVRow
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowOregonState_noComma()]
changed conditional boundary → KILLED

2.2
Location : fromOregonStateCSVRow
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowOregonState()]
negated conditional → KILLED

238

1.1
Location : fromOregonStateCSVRow
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowOregonState()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromOregonStateCSVRow → KILLED

256

1.1
Location : getFirstName
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_getFirstname()]
negated conditional → KILLED

259

1.1
Location : getFirstName
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_getFirstname()]
replaced return value with "" for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::getFirstName → KILLED

271

1.1
Location : getLastName
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_getLastName()]
negated conditional → KILLED

272

1.1
Location : getLastName
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_getLastName()]
replaced return value with "" for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::getLastName → KILLED

274

1.1
Location : getLastName
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_getLastName()]
Replaced integer addition with subtraction → KILLED

2.2
Location : getLastName
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_getLastName()]
replaced return value with "" for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::getLastName → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0