
1package autograder;2import java.io.PrintStream;3import java.lang.annotation.*;4import java.util.*;5import kvstore.*;6import org.junit.FixMethodOrder;7import org.junit.experimental.categories.*;8import org.junit.experimental.categories.Categories.IncludeCategory;9import org.junit.runner.*;10import org.junit.runners.*;11public final class AGCategories {12    // JUnit Categories13    public interface AG_CS162 {}14    public interface AG_PROJ3 extends AG_CS162 {}15    public interface AG_PROJ3_TEST extends AG_PROJ3 {}16    public interface AG_PROJ3_CODE extends AG_PROJ3 {}17    public interface AG_PROJ4 extends AG_CS162 {}18    public interface AG_PROJ4_TEST extends AG_PROJ4 {}19    public interface AG_PROJ4_CODE extends AG_PROJ4 {}20    // JUnit Suites (defined by categories)21    @RunWith(Categories.class)22    @Suite.SuiteClasses({23        EndToEndTest.class,24        KVCacheTest.class,25        KVClientTest.class,26        KVMessageTest.class,27        KVStoreTest.class,28        SocketServerTest.class,29        ThreadPoolTest.class,30        KVServerTest.class31    })32    @IncludeCategory(AG_PROJ3_CODE.class)33    @FixMethodOrder(MethodSorters.NAME_ASCENDING)34    public static class AGSuite_proj3_code {}35    @IncludeCategory(AG_PROJ3_TEST.class)36    @FixMethodOrder(MethodSorters.NAME_ASCENDING)37    public static class AGSuite_proj3_test extends AGSuite_proj3_code {}38    @RunWith(Categories.class)39    @Suite.SuiteClasses({40    })41    @FixMethodOrder(MethodSorters.NAME_ASCENDING)42    @IncludeCategory(AG_PROJ4_CODE.class)43    public static class AGSuite_proj4_code {}44    @FixMethodOrder(MethodSorters.NAME_ASCENDING)45    @IncludeCategory(AG_PROJ4_TEST.class)46    public static class AGSuite_proj4_test extends AGSuite_proj4_code {}47    @Retention(RetentionPolicy.RUNTIME)48    @Target(ElementType.METHOD)49    public @interface AGTestDetails {50        // int uid(); // Unique ID (manually chosen)51        float points() default Float.NaN; // Points during grading52        String desc(); // Public description for students53        String developNotes() default ""; // Private description for AG developers/TA's54        String testFamily() default ""; // If blank, just uses class name55        boolean isPublic() default true; // Made available in public auto-autograder56    }57    public static String getTestTitle(Description d) {58        AGTestDetails details = d.getAnnotation(AGTestDetails.class);59        if (details == null) return d.getMethodName();60        return String.format("%s", d.getDisplayName());61    }62    public static String getTestDesc(Description d) {63        AGTestDetails details = d.getAnnotation(AGTestDetails.class);64        if (details == null) return d.getDisplayName();65        return details.desc();66    }67    public static String getTestFamily(Description d) {68        AGTestDetails details = d.getAnnotation(AGTestDetails.class);69        String family = (details == null) ? null : details.testFamily();70        if ((family == null) || family.isEmpty()) {71            family = d.getTestClass().getSimpleName();72        }73        return family;74    }75    public static String getTestWeights(Description d, boolean showAll) {76        AGTestDetails details = d.getAnnotation(AGTestDetails.class);77        if (details == null) return (showAll) ? "??? 0 " + d.getDisplayName() : null;78        return (!((details.points() > 0.0f) || showAll)) ? null79                : String.format("%s %d %s", d.getDisplayName(),80                        Math.round(details.points()), getTestFamily(d));81    }82    public static String getTestDetailText(Description d) {83        AGTestDetails details = d.getAnnotation(AGTestDetails.class);84        if (details == null) return d.getDisplayName();85        return String.format("%s %.2f %s [%s] %s", d.getDisplayName(),86                details.points(), getTestFamily(d),87                details.isPublic() ? "public" : "private",88                details.desc());89    }90    static enum AGSuite {91        proj3_test(AGSuite_proj3_test.class),92        proj3_code(AGSuite_proj3_code.class),93        proj4_test(AGSuite_proj4_test.class),94        proj4_code(AGSuite_proj4_code.class);95        private Class<?> suiteClass;96        AGSuite(Class<?> suite) {97            suiteClass = suite;98        }99        public Request getJUnitRequest() {100            return Request.aClass(suiteClass);101        }102    }103    public static boolean runJUnitTests(final Request request) {104        // TODO: Explicitly take two streams, then redirect & restore stdout/err105        PrintStream psOut = System.err;106        System.setErr(System.out);107        Calendar startCal = Calendar.getInstance();108        System.out.format("AutoGrader Run: %1tc%n%n", startCal);109        System.out.println("========================== DISPLAYING FAILED TESTS ==========================");110        System.out.flush();111        // psOut.format("START-ALL: %1tc%n", startCal);112        // Perform the JUnit run proper113        SuccessListener jlistener = new SuccessListener(request, System.err, System.err);//psOut);114        JUnitCore jcore = new JUnitCore();115        jcore.addListener(jlistener);116        // Result result = jcore.run(request);117        jcore.run(request);118        boolean perfectOnRequired = (jlistener.testsLost == 0);119        // Report on the run in various summary forms120        // jlistener.logSummary(System.err, true);121        // jlistener.logSummary(System.err, false);122        // jlistener.logSummary(psOut, true);123        // Just encourage finalization of stuff (probably useless)124        // result = null;125        jlistener = null;126        jcore = null;127        System.gc();128        System.runFinalization();129        System.err.flush();130        psOut.flush();131        // Calendar finishCal = Calendar.getInstance();132        // System.out.format("%n%nFINISH-ALL: %1tc  [ ELAPSED: %2tT ]%n%n",133        //         finishCal, TestUtils.elapsedTime(startCal, finishCal));134        return perfectOnRequired;135    }136    public static void listTests(Description desc, int level) {137        int nextLevel = level + (int) Math.signum(level);138        List<Description> reqList = desc.getChildren();139        if ((level > 0) || desc.isTest()) {140            String line = null;141            if (level == 0) {142                line = getTestWeights(desc, false);143            } else if (level > 0) {144                line = getTestDetailText(desc);145                if (line != null) {146                    line = TestUtils.indentStr(level - 1, "\t") + line;147                }148            } else {149                line = getTestDetailText(desc);150            }151            if (line != null) {152                System.out.println(line);153            }154        }155        for (Description child: reqList) {156            listTests(child, nextLevel);157        }158    }159}...
