001package edu.pdx.cs.joy.grader;
002
003import com.google.common.io.ByteStreams;
004import edu.pdx.cs.joy.grader.gradebook.Assignment;
005import edu.pdx.cs.joy.grader.gradebook.Grade;
006import edu.pdx.cs.joy.grader.gradebook.GradeBook;
007import edu.pdx.cs.joy.grader.gradebook.Student;
008import org.hamcrest.MatcherAssert;
009import org.junit.jupiter.api.Test;
010
011import java.io.ByteArrayInputStream;
012import java.io.ByteArrayOutputStream;
013import java.io.IOException;
014import java.time.LocalDateTime;
015import java.util.HashMap;
016import java.util.zip.ZipEntry;
017import java.util.zip.ZipInputStream;
018import java.util.zip.ZipOutputStream;
019
020import static org.hamcrest.MatcherAssert.assertThat;
021import static org.hamcrest.core.IsEqual.equalTo;
022import static org.hamcrest.core.IsNull.notNullValue;
023import static org.hamcrest.core.IsNull.nullValue;
024
025public class AndroidZipFixerTest {
026
027  @Test
028  public void unitTestEntriesAreIgnored() {
029    assertThat(AndroidZipFixer.getFixedEntryName("src/test/java"), equalTo(null));
030  }
031
032  @Test
033  public void androidTestEntriesAreIgnored() {
034    assertThat(AndroidZipFixer.getFixedEntryName("src/androidTest/java"), equalTo(null));
035  }
036
037  @Test
038  public void androidTestInDirectoryIsIgnored() {
039    String entry = "student/app/src/androidTest/java/edu/pdx/cs/joy/";
040    assertThat(AndroidZipFixer.getFixedEntryName(entry), equalTo(null));
041  }
042
043  @Test
044  public void buildDirectoriesAreIgnored() {
045    assertThat(AndroidZipFixer.getFixedEntryName("build"), equalTo(null));
046  }
047
048  @Test
049  public void buildGradleRemainsAtTopLevel() {
050    assertThat(AndroidZipFixer.getFixedEntryName("build.gradle"), equalTo("build.gradle"));
051  }
052
053  @Test
054  public void buildGradleInAppDirectoryRemainsInItsDirectory() {
055    assertThat(AndroidZipFixer.getFixedEntryName("app/build.gradle"), equalTo("app/build.gradle"));
056  }
057
058  @Test
059  public void buildGradleInNonAppDirectoryIsMoveToTop() {
060    assertThat(AndroidZipFixer.getFixedEntryName("fred/build.gradle"), equalTo("build.gradle"));
061  }
062
063  @Test
064  public void buildGradleInAppDirectoryInOtherDirectoryIsMovedToTopAppDirectory() {
065    assertThat(AndroidZipFixer.getFixedEntryName("fred/app/build.gradle"), equalTo("app/build.gradle"));
066  }
067
068  @Test
069  public void gradlePropertiesRemainsAtTopLevel() {
070    assertThat(AndroidZipFixer.getFixedEntryName("gradle.properties"), equalTo("gradle.properties"));
071  }
072
073  @Test
074  public void gradlePropertiesMovedToTopLevel() {
075    assertThat(AndroidZipFixer.getFixedEntryName("fred/gradle.properties"), equalTo("gradle.properties"));
076  }
077
078  @Test
079  public void gradleDirectoryMovedToTopLevel() {
080    assertThat(AndroidZipFixer.getFixedEntryName("fred/gradle"), equalTo("gradle"));
081  }
082
083  @Test
084  public void gradlewScriptMovedToTopLevel() {
085    assertThat(AndroidZipFixer.getFixedEntryName("fred/gradlew"), equalTo("gradlew"));
086  }
087
088  @Test
089  public void settingsDotGradleScriptMovedToTopLevel() {
090    assertThat(AndroidZipFixer.getFixedEntryName("fred/settings.gradle"), equalTo("settings.gradle"));
091  }
092
093  @Test
094  public void localDotPropertiesIsIgnored() {
095    assertThat(AndroidZipFixer.getFixedEntryName("fred/local.properties"), equalTo(null));
096  }
097
098  @Test
099  public void gradleWrapperJarFileMovedToTopLevel() {
100    String entry = "gradle/wrapper/gradle-wrapper.jar";
101    assertThat(AndroidZipFixer.getFixedEntryName("student/" + entry), equalTo(entry));
102  }
103
104  @Test
105  public void gradlewDotBatIsIgnored() {
106    assertThat(AndroidZipFixer.getFixedEntryName("student/gradlew.bat"), equalTo(null));
107  }
108
109  @Test
110  public void javaSourceRemainsAtTopLevel() {
111    String entry = "app/src/main/java/edu/pdx/cs/joy/student/client/MainActivity.java";
112    assertThat(AndroidZipFixer.getFixedEntryName(entry), equalTo(entry));
113  }
114
115  @Test
116  public void javaSourceIsMovedToTopLevel() {
117    String entry = "app/src/main/java/edu/pdx/cs/joy/student/client/MainActivity.java";
118    assertThat(AndroidZipFixer.getFixedEntryName("directory/" + entry), equalTo(entry));
119  }
120
121  @Test
122  public void ideaDirectoryIsIgnored() {
123    String entry = "5Proj/apptbook-gwt/.idea/artifacts/";
124    assertThat(AndroidZipFixer.getFixedEntryName(entry), equalTo(null));
125  }
126
127  @Test
128  public void imlFilesAreIgnored() {
129    assertThat(AndroidZipFixer.getFixedEntryName("project.iml"), equalTo(null));
130  }
131
132  @Test
133  public void resourcesDirectoryIsMovedToTopLevel() {
134    String resource = "app/src/main/res/mipmap-mdpi/ic_launcher.png";
135    String entry = "5Proj/apptbook-gwt" + resource;
136    assertThat(AndroidZipFixer.getFixedEntryName(entry), equalTo(resource));
137  }
138
139  @Test
140  public void srcIsAddedToMainDirectory() {
141    String entry = "main/java/edu/pdx/cs/joy/student/client/PrettyPrinter.java";
142    assertThat(AndroidZipFixer.getFixedEntryName(entry), equalTo("app/src/" + entry));
143  }
144
145  @Test
146  public void macosDirectoryIsIgnored() {
147    String entry = "__MACOSX/apptbook-gwt/._pom.xml";
148    assertThat(AndroidZipFixer.getFixedEntryName(entry), equalTo(null));
149  }
150  @Test
151  public void mainThatIsNotSourceMainIsIgnored() {
152    String entry = "apptbook-gwt/out/production/main/";
153    assertThat(AndroidZipFixer.getFixedEntryName(entry), equalTo(null));
154  }
155
156  @Test
157  public void directoryWithJavaIsMovedToSrcMain() {
158    String entry = "student/java/edu/pdx/cs/joy/student/client/Appointment.java";
159    String fixed = "app/src/main/java/edu/pdx/cs/joy/student/client/Appointment.java";
160    assertThat(AndroidZipFixer.getFixedEntryName(entry), equalTo(fixed));
161  }
162
163  @Test
164  public void srcTestIsIgnored() {
165    String entry = "apptbook-gwt-submission/src/test/java/edu/";
166    assertThat(AndroidZipFixer.getFixedEntryName(entry), equalTo(null));
167  }
168
169  @Test
170  public void srcAndroidTestIsIgnored() {
171    String entry = "apptbook-gwt-submission/src/androidTest/java/edu/";
172    assertThat(AndroidZipFixer.getFixedEntryName(entry), equalTo(null));
173  }
174
175  @Test
176  public void directoryWithJavaSubPackageNamedDomainIsMovedToSrcMain() {
177    String entry = "student/java/edu/pdx/cs/joy/student/client/domain/Appointment.java";
178    String fixed = "app/src/main/java/edu/pdx/cs/joy/student/client/domain/Appointment.java";
179    assertThat(AndroidZipFixer.getFixedEntryName(entry), equalTo(fixed));
180  }
181
182  @Test
183  public void directoryWithJavaSubPackageNamedDomainRemainsInSrcMain() {
184    String entry = "app/src/main/java/edu/pdx/cs/joy/student/client/domain/Appointment.java";
185    assertThat(AndroidZipFixer.getFixedEntryName(entry), equalTo(entry));
186  }
187
188  @Test
189  public void fileSubmittedWithSubmitProgramIsMovedToSrcMainJava() {
190    String entry = "edu/pdx/cs/joy/student/client/domain/Appointment.java";
191    String fixed = "app/src/main/java/edu/pdx/cs/joy/student/client/domain/Appointment.java";
192    assertThat(AndroidZipFixer.getFixedEntryName(entry), equalTo(fixed));
193  }
194
195  @Test
196  public void packageWithMainIsMovedToAppropriateLocation() {
197    String entry = "AndroidAppointmentBook/app/src/main/java/edu/pdx/cs/joy/student/androidappointmentbook/ui/main/SectionsPagerAdapter.java";
198    String fixed = "app/src/main/java/edu/pdx/cs/joy/student/androidappointmentbook/ui/main/SectionsPagerAdapter.java";
199    assertThat(AndroidZipFixer.getFixedEntryName(entry), equalTo(fixed));
200  }
201
202  @Test
203  public void pomFileInTargetIsIgnored() {
204    String entry = "airline-gwt/target/airline/META-INF/maven/edu.pdx.cs.joy.student/airline-gwt/pom.xml";
205    assertThat(AndroidZipFixer.getFixedEntryName(entry), nullValue());
206  }
207
208  @Test
209  public void dsStoreIsIgnored() {
210    String entry = "student/airline/src/main/.DS_Store";
211    assertThat(AndroidZipFixer.getFixedEntryName(entry), nullValue());
212  }
213
214  @Test
215  public void manifestContainsStudentId() {
216    String studentId = "studentId";
217
218    GradeBook book = new GradeBook("test");
219    book.addStudent(new Student(studentId));
220
221    AndroidZipFixer fixer = new AndroidZipFixer(book);
222    assertThat(fixer.getManifestEntriesForStudent(studentId).get(Submit.ManifestAttributes.USER_ID), equalTo(studentId));
223  }
224
225  @Test
226  public void manifestContainsStudentName() {
227
228    GradeBook book = new GradeBook("test");
229    Student student = new Student("studentId");
230    student.setFirstName("First");
231    student.setLastName("Last");
232    book.addStudent(student);
233
234    AndroidZipFixer fixer = new AndroidZipFixer(book);
235    assertThat(fixer.getManifestEntriesForStudent("studentId").get(Submit.ManifestAttributes.USER_NAME), equalTo(student.getFullName()));
236
237  }
238
239  @Test
240  public void manifestContainsSubmissionTime() {
241    GradeBook book = new GradeBook("test");
242    String studentId = "studentId";
243    Student student = new Student(studentId);
244    book.addStudent(student);
245
246    Assignment gwtProject = new Assignment("Project5", 12.0);
247    book.addAssignment(gwtProject);
248
249    Grade grade = new Grade(gwtProject, Grade.NO_GRADE);
250    LocalDateTime submissionTime = LocalDateTime.now();
251    grade.noteSubmission(submissionTime);
252
253    student.setGrade(gwtProject, grade);
254
255    AndroidZipFixer fixer = new AndroidZipFixer(book);
256    MatcherAssert.assertThat(fixer.getManifestEntriesForStudent(studentId).get(Submit.ManifestAttributes.SUBMISSION_TIME), equalTo(Submit.ManifestAttributes.formatSubmissionTime(submissionTime)));
257  }
258
259  @Test
260  public void manifestContainsLatestSubmissionTime() {
261    GradeBook book = new GradeBook("test");
262    String studentId = "studentId";
263    Student student = new Student(studentId);
264    book.addStudent(student);
265
266    Assignment gwtProject = new Assignment("Project5", 12.0);
267    book.addAssignment(gwtProject);
268
269    Grade grade = new Grade(gwtProject, Grade.NO_GRADE);
270    LocalDateTime now = LocalDateTime.now();
271    LocalDateTime firstSubmissionTime = now.minusDays(1);
272    grade.noteSubmission(firstSubmissionTime);
273    LocalDateTime secondSubmissionTime = now.minusHours(6);
274    grade.noteSubmission(secondSubmissionTime);
275
276    student.setGrade(gwtProject, grade);
277
278    AndroidZipFixer fixer = new AndroidZipFixer(book);
279    MatcherAssert.assertThat(fixer.getManifestEntriesForStudent(studentId).get(Submit.ManifestAttributes.SUBMISSION_TIME), equalTo(Submit.ManifestAttributes.formatSubmissionTime(secondSubmissionTime)));
280  }
281
282  @Test
283  public void missingSubmissionDateResultsInNullManifestEntry() {
284    GradeBook book = new GradeBook("test");
285    String studentId = "studentId";
286    Student student = new Student(studentId);
287    book.addStudent(student);
288
289    Assignment gwtProject = new Assignment("Project5", 12.0);
290    book.addAssignment(gwtProject);
291
292    Grade grade = new Grade(gwtProject, Grade.NO_GRADE);
293
294    student.setGrade(gwtProject, grade);
295
296    AndroidZipFixer fixer = new AndroidZipFixer(book);
297    assertThat(fixer.getManifestEntriesForStudent(studentId).get(Submit.ManifestAttributes.SUBMISSION_TIME), equalTo(null));
298  }
299
300  @Test
301  public void contentsOfZipEntriesAreNotModified() throws IOException {
302    String entryName = "build.gradle";
303    String entryContent = "This is a test entry";
304
305    ByteArrayOutputStream zippedBytes = new ByteArrayOutputStream();
306    ZipOutputStream zos = new ZipOutputStream(zippedBytes);
307    zos.setMethod(ZipOutputStream.DEFLATED);
308
309    ZipEntry entry = new ZipEntry(entryName);
310    zos.putNextEntry(entry);
311    zos.write(entryContent.getBytes());
312    zos.closeEntry();
313    zos.close();
314
315    AndroidZipFixer fixer = new AndroidZipFixer(new GradeBook("test"));
316    ByteArrayOutputStream fixedBytes = new ByteArrayOutputStream();
317    fixer.fixZipFile(new ByteArrayInputStream(zippedBytes.toByteArray()), fixedBytes, new HashMap<>());
318
319    ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(fixedBytes.toByteArray()));
320
321    ZipEntry fixedEntry = zis.getNextEntry();
322    while (fixedEntry != null) {
323      if (fixedEntry.getName().equals(entryName)) {
324        break;
325      }
326      fixedEntry = zis.getNextEntry();
327    }
328
329    assertThat(fixedEntry, notNullValue());
330
331    ByteArrayOutputStream fixedEntryBytes = new ByteArrayOutputStream();
332    ByteStreams.copy(zis, fixedEntryBytes);
333    String fixedEntryContent = new String(fixedEntryBytes.toByteArray());
334
335    assertThat(fixedEntryContent, equalTo(entryContent));
336
337
338  }
339
340}