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
    ROSTER_DOWNLOAD,
62
    UNKNOWN
63
  }
64
65
  public static final String UCSB_EGRADES_HEADERS =
66
      "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";
67
  public static final String CHICO_CANVAS_HEADERS =
68
      "Student Name,Student ID,Student SIS ID,Email,Section Name";
69
  public static final String OREGON_STATE_HEADERS =
70
      "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";
71
  public static final String ROSTER_DOWNLOAD_HEADERS =
72
      "COURSEID,EMAIL,FIRSTNAME,GITHUBID,GITHUBLOGIN,ID,LASTNAME,ORGSTATUS,ROSTERSTATUS,SECTION,STUDENTID,TEAMS,USERID";
73
74
  public static RosterSourceType getRosterSourceType(String[] headers) {
75
76
    Map<RosterSourceType, String[]> sourceTypeToHeaders = new HashMap<>();
77
78
    sourceTypeToHeaders.put(RosterSourceType.UCSB_EGRADES, UCSB_EGRADES_HEADERS.split(","));
79
    sourceTypeToHeaders.put(RosterSourceType.CHICO_CANVAS, CHICO_CANVAS_HEADERS.split(","));
80
    sourceTypeToHeaders.put(RosterSourceType.OREGON_STATE, OREGON_STATE_HEADERS.split(","));
81
    sourceTypeToHeaders.put(RosterSourceType.ROSTER_DOWNLOAD, ROSTER_DOWNLOAD_HEADERS.split(","));
82
83
    for (Map.Entry<RosterSourceType, String[]> entry : sourceTypeToHeaders.entrySet()) {
84
      RosterSourceType type = entry.getKey();
85
      String[] expectedHeaders = entry.getValue();
86 2 1. getRosterSourceType : changed conditional boundary → KILLED
2. getRosterSourceType : negated conditional → KILLED
      if (headers.length >= expectedHeaders.length) {
87
        boolean matches = true;
88 2 1. getRosterSourceType : negated conditional → KILLED
2. getRosterSourceType : changed conditional boundary → KILLED
        for (int i = 0; i < expectedHeaders.length; i++) {
89 1 1. getRosterSourceType : negated conditional → KILLED
          if (!expectedHeaders[i].trim().equalsIgnoreCase(headers[i].trim())) {
90
            matches = false;
91
            break;
92
          }
93
        }
94 1 1. getRosterSourceType : negated conditional → KILLED
        if (matches) {
95 1 1. getRosterSourceType : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::getRosterSourceType → KILLED
          return type;
96
        }
97
      }
98
    }
99
    // If no known type matches, return UNKNOWN
100 1 1. getRosterSourceType : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::getRosterSourceType → KILLED
    return RosterSourceType.UNKNOWN;
101
  }
102
103
  /**
104
   * Upload Roster students for Course in any supported format. It is important to keep the code in
105
   * this method consistent with the code for adding a single roster student
106
   *
107
   * @param courseId
108
   * @param file
109
   * @return
110
   * @throws JsonProcessingException
111
   * @throws IOException
112
   * @throws CsvException
113
   */
114
  @Operation(summary = "Upload Roster students for Course in any supported Format")
115
  @PreAuthorize("@CourseSecurity.hasManagePermissions(#root, #courseId)")
116
  @PostMapping(
117
      value = "/upload/csv",
118
      consumes = {"multipart/form-data"})
119
  public ResponseEntity<LoadResult> uploadRosterStudentsCSV(
120
      @Parameter(name = "courseId") @RequestParam Long courseId,
121
      @Parameter(name = "file") @RequestParam("file") MultipartFile file)
122
      throws JsonProcessingException, IOException, CsvException {
123
124
    Course course =
125
        courseRepository
126
            .findById(courseId)
127 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()));
128
129
    course.getRosterStudents().stream()
130 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)
131 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));
132
133
    int counts[] = {0, 0};
134
    List<RosterStudent> rejectedStudents = new ArrayList<>();
135
136
    try (InputStream inputStream = new BufferedInputStream(file.getInputStream());
137
        InputStreamReader reader = new InputStreamReader(inputStream);
138
        CSVReader csvReader = new CSVReader(reader); ) {
139
140
      String[] headers = csvReader.readNext();
141
      RosterSourceType sourceType = getRosterSourceType(headers);
142 1 1. uploadRosterStudentsCSV : negated conditional → KILLED
      if (sourceType == RosterSourceType.UNKNOWN) {
143
        throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Unknown Roster Source Type");
144
      }
145 1 1. uploadRosterStudentsCSV : negated conditional → KILLED
      if (sourceType == RosterSourceType.UCSB_EGRADES) {
146 1 1. uploadRosterStudentsCSV : removed call to com/opencsv/CSVReader::skip → KILLED
        csvReader.skip(1);
147
      }
148
      List<String[]> myEntries = csvReader.readAll();
149
      for (String[] row : myEntries) {
150
        RosterStudent rosterStudent = fromCSVRow(row, sourceType);
151
        UpsertResponse upsertResponse =
152
            RosterStudentsController.upsertStudent(rosterStudent, course, RosterStatus.ROSTER);
153 1 1. uploadRosterStudentsCSV : negated conditional → KILLED
        if (upsertResponse.getInsertStatus() == InsertStatus.REJECTED) {
154
          rejectedStudents.add(upsertResponse.rosterStudent());
155
        } else {
156
          InsertStatus s = upsertResponse.getInsertStatus();
157 1 1. uploadRosterStudentsCSV : negated conditional → KILLED
          if (s == InsertStatus.INSERTED) {
158
            course.getRosterStudents().add(upsertResponse.rosterStudent());
159
          }
160 1 1. uploadRosterStudentsCSV : Replaced integer addition with subtraction → KILLED
          counts[s.ordinal()]++;
161
        }
162
      }
163
    }
164 1 1. uploadRosterStudentsCSV : negated conditional → KILLED
    if (rejectedStudents.isEmpty()) {
165
      List<RosterStudent> droppedStudents =
166
          course.getRosterStudents().stream()
167 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)
168
              .toList();
169
      LoadResult successfulResult =
170
          new LoadResult(
171
              counts[InsertStatus.INSERTED.ordinal()],
172
              counts[InsertStatus.UPDATED.ordinal()],
173
              droppedStudents.size(),
174
              List.of());
175
      rosterStudentRepository.saveAll(course.getRosterStudents());
176 1 1. uploadRosterStudentsCSV : removed call to edu/ucsb/cs156/frontiers/services/UpdateUserService::attachUsersToRosterStudents → KILLED
      updateUserService.attachUsersToRosterStudents(course.getRosterStudents());
177
      RemoveStudentsJob job =
178
          RemoveStudentsJob.builder()
179
              .students(droppedStudents)
180
              .organizationMemberService(organizationMemberService)
181
              .rosterStudentRepository(rosterStudentRepository)
182
              .build();
183
      jobService.runAsJob(job);
184 1 1. uploadRosterStudentsCSV : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::uploadRosterStudentsCSV → KILLED
      return ResponseEntity.ok(successfulResult);
185
    } else {
186
      LoadResult conflictResult = new LoadResult(0, 0, 0, rejectedStudents);
187 1 1. uploadRosterStudentsCSV : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::uploadRosterStudentsCSV → KILLED
      return ResponseEntity.status(HttpStatus.CONFLICT).body(conflictResult);
188
    }
189
  }
190
191
  public static RosterStudent fromCSVRow(String[] row, RosterSourceType sourceType) {
192 1 1. fromCSVRow : negated conditional → KILLED
    if (sourceType == RosterSourceType.UCSB_EGRADES) {
193 1 1. fromCSVRow : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromCSVRow → KILLED
      return fromUCSBEgradesCSVRow(row);
194 1 1. fromCSVRow : negated conditional → KILLED
    } else if (sourceType == RosterSourceType.CHICO_CANVAS) {
195 1 1. fromCSVRow : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromCSVRow → KILLED
      return fromChicoCanvasCSVRow(row);
196 1 1. fromCSVRow : negated conditional → KILLED
    } else if (sourceType == RosterSourceType.OREGON_STATE) {
197 1 1. fromCSVRow : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromCSVRow → KILLED
      return fromOregonStateCSVRow(row);
198 1 1. fromCSVRow : negated conditional → KILLED
    } else if (sourceType == RosterSourceType.ROSTER_DOWNLOAD) {
199 1 1. fromCSVRow : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromCSVRow → KILLED
      return fromRosterDownloadCSVRow(row);
200
    } else {
201
      throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "CSV format not recognized");
202
    }
203
  }
204
205
  public static void checkRowLength(String[] row, int expectedLength, RosterSourceType sourceType) {
206 2 1. checkRowLength : changed conditional boundary → KILLED
2. checkRowLength : negated conditional → KILLED
    if (row.length < expectedLength) {
207
      throw new ResponseStatusException(
208
          HttpStatus.BAD_REQUEST,
209
          String.format(
210
              "%s CSV row does not have enough columns. Length = %d Row content = [%s]",
211
              sourceType.toString(), row.length, Arrays.toString(row)));
212
    }
213
  }
214
215
  public static RosterStudent fromUCSBEgradesCSVRow(String[] row) {
216 1 1. fromUCSBEgradesCSVRow : removed call to edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::checkRowLength → KILLED
    checkRowLength(row, 11, RosterSourceType.UCSB_EGRADES);
217 1 1. fromUCSBEgradesCSVRow : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromUCSBEgradesCSVRow → KILLED
    return RosterStudent.builder()
218
        .firstName(row[5])
219
        .lastName(row[4])
220
        .studentId(row[1])
221
        .email(row[10])
222
        .section(row[0])
223
        .build();
224
  }
225
226
  public static RosterStudent fromChicoCanvasCSVRow(String[] row) {
227 1 1. fromChicoCanvasCSVRow : removed call to edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::checkRowLength → KILLED
    checkRowLength(row, 4, RosterSourceType.CHICO_CANVAS);
228 1 1. fromChicoCanvasCSVRow : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromChicoCanvasCSVRow → KILLED
    return RosterStudent.builder()
229
        .firstName(getFirstName(row[0]))
230
        .lastName(getLastName(row[0]))
231
        .studentId(row[2])
232
        .email(row[3])
233
        .section("")
234
        .build();
235
  }
236
237
  public static RosterStudent fromOregonStateCSVRow(String[] row) {
238
239 1 1. fromOregonStateCSVRow : removed call to edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::checkRowLength → KILLED
    checkRowLength(row, 10, RosterSourceType.OREGON_STATE);
240
    String sortableName = row[1];
241
    String sortableNameParts[] = sortableName.split(",");
242
    String lastName = sortableNameParts[0].trim();
243 2 1. fromOregonStateCSVRow : changed conditional boundary → KILLED
2. fromOregonStateCSVRow : negated conditional → KILLED
    String firstName = sortableNameParts.length > 1 ? sortableNameParts[1].trim() : "";
244 1 1. fromOregonStateCSVRow : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromOregonStateCSVRow → KILLED
    return RosterStudent.builder()
245
        .firstName(firstName)
246
        .lastName(lastName)
247
        .studentId(row[9])
248
        .email(row[8])
249
        .section("")
250
        .build();
251
  }
252
253
  public static RosterStudent fromRosterDownloadCSVRow(String[] row) {
254
    // Header order: COURSEID, EMAIL, FIRSTNAME, GITHUBID, GITHUBLOGIN, ID, LASTNAME,
255
    // ORGSTATUS, ROSTERSTATUS, SECTION, STUDENTID, TEAMS, USERID
256 1 1. fromRosterDownloadCSVRow : removed call to edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::checkRowLength → KILLED
    checkRowLength(row, 13, RosterSourceType.ROSTER_DOWNLOAD);
257 1 1. fromRosterDownloadCSVRow : replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromRosterDownloadCSVRow → KILLED
    return RosterStudent.builder()
258
        .firstName(row[2])
259
        .lastName(row[6])
260
        .studentId(row[10])
261
        .email(row[1])
262
        .section(row[9])
263
        .build();
264
  }
265
266
  /**
267
   * Get everything except up to and not including the last space in the full name. If the string
268
   * contains no spaces, return an empty string.
269
   *
270
   * @param fullName
271
   * @return
272
   */
273
  public static String getFirstName(String fullName) {
274
    int lastSpaceIndex = fullName.lastIndexOf(" ");
275 1 1. getFirstName : negated conditional → KILLED
    if (lastSpaceIndex == -1) {
276
      return ""; // No spaces found, return empty string
277
    }
278 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
279
  }
280
281
  /**
282
   * Get everything after the last space in the full name. If the string contains no spaces, return
283
   * the entire input string as the result.
284
   *
285
   * @param fullName
286
   * @return best estimate of last name
287
   */
288
  public static String getLastName(String fullName) {
289
    int lastSpaceIndex = fullName.lastIndexOf(" ");
290 1 1. getLastName : negated conditional → KILLED
    if (lastSpaceIndex == -1) {
291 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
292
    }
293 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
294
  }
295
}

Mutations

86

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

88

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

89

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

94

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

95

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

100

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

127

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

130

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

131

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

142

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

145

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()]
negated conditional → KILLED

146

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()]
removed call to com/opencsv/CSVReader::skip → 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:students_with_non_matching_student_id_and_email_are_rejected()]
negated conditional → KILLED

157

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

160

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

164

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()]
negated conditional → KILLED

167

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:updates_in_upsert_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:updates_in_upsert_correctly()]
negated conditional → KILLED

176

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

184

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

187

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

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_fromCSVRowChico_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_fromCSVRowUCSB_sectionField()]
replaced return value with null for edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::fromCSVRow → KILLED

194

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_notEnoughColumns()]
negated conditional → KILLED

195

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

196

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

197

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

198

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

199

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

206

1.1
Location : checkRowLength
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowRosterDownload_sectionField()]
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_fromCSVRowChico_notEnoughColumns()]
negated conditional → KILLED

216

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

217

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

227

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

228

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

239

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

243

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

244

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 : fromRosterDownloadCSVRow
Killed by : edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.frontiers.controllers.RosterStudentsCSVControllerTests]/[method:test_fromCSVRowRosterDownload_notEnoughColumns()]
removed call to edu/ucsb/cs156/frontiers/controllers/RosterStudentsCSVController::checkRowLength → KILLED

257

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

275

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

278

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

290

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

291

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

293

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