Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
import java.util.Scanner;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.FileSystems;
import java.io.*;
import java.net.URI;
import java.util.Arrays;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject.Kind;
public class Tester {
public static void cleanup() throws IOException {
Files.deleteIfExists(FileSystems.getDefault().getPath("DirectRun.class"));
Files.deleteIfExists(FileSystems.getDefault().getPath("OnMySourceCodeGENERATOR.class"));
}
public static void main(String args[]) throws IOException {
/* Delete all existing .class files to makes sure we're working fresh. */
cleanup();
/* Create a new compiler. */
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
/* Read in the student OnMySourceCodeGENERATOR.java file */
String OnMySourceCodeGENERATOR = new Scanner(new File("OnMySourceCodeGENERATOR.java")).useDelimiter("\\Z").next();
/* Create a file for the student code. */
JavaFileObject studentCode = new JavaSourceFromString("OnMySourceCodeGENERATOR", OnMySourceCodeGENERATOR);
/* Read in the P.input file; so, we know what function we're computing. */
String P = new Scanner(new File("P.input")).useDelimiter("\\Z").next();
/* Create the DirectRun class to test the output. */
StringWriter writer = new StringWriter();
PrintWriter out = new PrintWriter(writer);
out.println("public class DirectRun {");
out.println(P);
out.println("}");
out.close();
JavaFileObject directRun = new JavaSourceFromString("DirectRun", writer.toString());
ByteArrayOutputStream baos;
Iterable<? extends JavaFileObject> compilationUnits;
CompilationTask task;
boolean compilationSuccess;
/* Compile the student code */
compilationUnits = Arrays.asList(studentCode);
task = compiler.getTask(null, null, null, null, null, compilationUnits);
compilationSuccess = task.call();
/* Redirect output; so, we can capture the generated code. */
baos = new ByteArrayOutputStream();
System.setOut(new PrintStream(baos));
/* Run the student code if we can; otherwise, exit. */
if (compilationSuccess == false) {
System.err.println("Your OnMySourceCodeGENERATOR.java file failed to compile!");
cleanup();
System.exit(1);
}
else {
try {
Class.forName("OnMySourceCodeGENERATOR").getDeclaredMethod("OnMySourceCodeGENERATOR", String.class).invoke(null, P);
} catch (Exception e) {
System.err.println("Something weird went wrong running your code. This should never happen. Come to office hours?\n" + e);
cleanup();
System.exit(1);
}
}
String POnMySourceCode = baos.toString();
System.err.println(POnMySourceCode);
JavaFileObject POMSC = new JavaSourceFromString("POnMySourceCode", POnMySourceCode);
/* Compile the POnMySourceCode code */
compilationUnits = Arrays.asList(POMSC);
task = compiler.getTask(null, null, null, null, null, compilationUnits);
compilationSuccess = task.call();
/* Run the student code if we can; otherwise, exit. */
if (compilationSuccess == false) {
System.err.println("POnMySourceCode (the code generated by OnMySourceCodeGENERATOR) is not valid Java code!");
cleanup();
System.exit(1);
}
/* Compile the DirectRun code */
compilationUnits = Arrays.asList(directRun);
task = compiler.getTask(null, null, null, null, null, compilationUnits);
compilationSuccess = task.call();
/* Redirect output; so, we can capture the correct answer. */
baos = new ByteArrayOutputStream();
System.setOut(new PrintStream(baos));
/* Run the student code if we can; otherwise, exit. */
if (compilationSuccess == false) {
System.err.println("P.input is not valid Java code!");
cleanup();
System.exit(1);
}
else {
try {
Class.forName("DirectRun").getDeclaredMethod("P", String.class).invoke(null, POnMySourceCode);
} catch (Exception e) {
System.err.println("Something weird went wrong running DirectRun. This should never happen. Come to office hours?\n" + e);
cleanup();
System.exit(1);
}
}
String correctBytes = baos.toString();
cleanup();
/* Redirect output; so, we can capture the student's answer. */
baos = new ByteArrayOutputStream();
System.setOut(new PrintStream(baos));
try {
Class.forName("POnMySourceCode").getDeclaredMethod("main", new Class[] { String[].class }).invoke(null, new Object[] { null });
} catch (Exception e) {
System.err.println("Something weird went wrong running POnMySourceCode. This should never happen. Come to office hours?\n" + e);
cleanup();
System.exit(1);
}
String studentBytes = baos.toString();
System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out)));
String BARRIER = "";
for (int i=0; i < 80; i++) {
BARRIER += "-";
}
System.out.println(BARRIER);
System.out.println("Your Output Was:");
System.out.println(BARRIER);
System.out.println("<" + studentBytes + ">");
System.out.println(BARRIER);
System.out.println();
System.out.println(BARRIER);
System.out.println("The Correct Output Was:");
System.out.println(BARRIER);
System.out.println("<" + correctBytes + ">");
System.out.println(BARRIER);
cleanup();
if (studentBytes.equals(correctBytes)) {
System.out.println("Yay! They match! You might want to try another P.input function to make sure it's actually working.");
cleanup();
System.exit(0);
}
else {
System.out.println("Nope. They are different somewhere. Try again.");
cleanup();
System.exit(1);
}
}
}
class JavaSourceFromString extends SimpleJavaFileObject {
final String code;
public JavaSourceFromString(String name, String code) {
super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension), Kind.SOURCE);
this.code = code;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return code;
}
}