p1/ag/AutoGrader.java

280 lines
7.6 KiB
Java

// PART OF THE MACHINE SIMULATION. DO NOT CHANGE.
package nachos.ag;
import nachos.machine.*;
import nachos.security.*;
import nachos.threads.*;
import java.util.Hashtable;
import java.util.StringTokenizer;
/**
* The default autograder. Loads the kernel, and then tests it using
* <tt>Kernel.selfTest()</tt>.
*/
public class AutoGrader {
/**
* Allocate a new autograder.
*/
public AutoGrader() {
}
/**
* Start this autograder. Extract the <tt>-#</tt> arguments, call
* <tt>init()</tt>, load and initialize the kernel, and call
* <tt>run()</tt>.
*
* @param privilege encapsulates privileged access to the Nachos
* machine.
*/
public void start(Privilege privilege) {
Lib.assertTrue(this.privilege == null,
"start() called multiple times");
this.privilege = privilege;
String[] args = Machine.getCommandLineArguments();
extractArguments(args);
System.out.print(" grader");
init();
System.out.print("\n");
kernel =
(Kernel) Lib.constructObject(Config.getString("Kernel.kernel"));
kernel.initialize(args);
run();
}
private void extractArguments(String[] args) {
String testArgsString = Config.getString("AutoGrader.testArgs");
if (testArgsString == null) {
testArgsString = "";
}
for (int i=0; i<args.length; ) {
String arg = args[i++];
if (arg.length() > 0 && arg.charAt(0) == '-') {
if (arg.equals("-#")) {
Lib.assertTrue(i < args.length,
"-# switch missing argument");
testArgsString = args[i++];
}
}
}
StringTokenizer st = new StringTokenizer(testArgsString, ",\n\t\f\r");
while (st.hasMoreTokens()) {
StringTokenizer pair = new StringTokenizer(st.nextToken(), "=");
Lib.assertTrue(pair.hasMoreTokens(),
"test argument missing key");
String key = pair.nextToken();
Lib.assertTrue(pair.hasMoreTokens(),
"test argument missing value");
String value = pair.nextToken();
testArgs.put(key, value);
}
}
String getStringArgument(String key) {
String value = (String) testArgs.get(key);
Lib.assertTrue(value != null,
"getStringArgument(" + key + ") failed to find key");
return value;
}
int getIntegerArgument(String key) {
try {
return Integer.parseInt(getStringArgument(key));
}
catch (NumberFormatException e) {
Lib.assertNotReached("getIntegerArgument(" + key + ") failed: " +
"value is not an integer");
return 0;
}
}
boolean getBooleanArgument(String key) {
String value = getStringArgument(key);
if (value.equals("1") || value.toLowerCase().equals("true")) {
return true;
}
else if (value.equals("0") || value.toLowerCase().equals("false")) {
return false;
}
else {
Lib.assertNotReached("getBooleanArgument(" + key + ") failed: " +
"value is not a boolean");
return false;
}
}
long getTime() {
return privilege.stats.totalTicks;
}
void targetLevel(int targetLevel) {
this.targetLevel = targetLevel;
}
void level(int level) {
this.level++;
Lib.assertTrue(level == this.level,
"level() advanced more than one step: test jumped ahead");
if (level == targetLevel)
done();
}
private int level = 0, targetLevel = 0;
void done() {
System.out.print("\nsuccess\n");
privilege.exit(162);
}
private Hashtable<String, String> testArgs =
new Hashtable<String, String>();
void init() {
}
void run() {
kernel.selfTest();
kernel.run();
kernel.terminate();
}
Privilege privilege = null;
Kernel kernel;
/**
* Notify the autograder that the specified thread is the idle thread.
* <tt>KThread.createIdleThread()</tt> <i>must</i> call this method before
* forking the idle thread.
*
* @param idleThread the idle thread.
*/
public void setIdleThread(KThread idleThread) {
}
/**
* Notify the autograder that the specified thread has moved to the ready
* state. <tt>KThread.ready()</tt> <i>must</i> call this method before
* returning.
*
* @param thread the thread that has been added to the ready set.
*/
public void readyThread(KThread thread) {
}
/**
* Notify the autograder that the specified thread is now running.
* <tt>KThread.restoreState()</tt> <i>must</i> call this method before
* returning.
*
* @param thread the thread that is now running.
*/
public void runningThread(KThread thread) {
privilege.tcb.associateThread(thread);
currentThread = thread;
}
/**
* Notify the autograder that the current thread has finished.
* <tt>KThread.finish()</tt> <i>must</i> call this method before putting
* the thread to sleep and scheduling its TCB to be destroyed.
*/
public void finishingCurrentThread() {
privilege.tcb.authorizeDestroy(currentThread);
}
/**
* Notify the autograder that a timer interrupt occurred and was handled by
* software if a timer interrupt handler was installed. Called by the
* hardware timer.
*
* @param privilege proves the authenticity of this call.
* @param time the actual time at which the timer interrupt was
* issued.
*/
public void timerInterrupt(Privilege privilege, long time) {
Lib.assertTrue(privilege == this.privilege,
"security violation");
}
/**
* Notify the autograder that a user program executed a syscall
* instruction.
*
* @param privilege proves the authenticity of this call.
* @return <tt>true</tt> if the kernel exception handler should be called.
*/
public boolean exceptionHandler(Privilege privilege) {
Lib.assertTrue(privilege == this.privilege,
"security violation");
return true;
}
/**
* Notify the autograder that <tt>Processor.run()</tt> was invoked. This
* can be used to simulate user programs.
*
* @param privilege proves the authenticity of this call.
*/
public void runProcessor(Privilege privilege) {
Lib.assertTrue(privilege == this.privilege,
"security violation");
}
/**
* Notify the autograder that a COFF loader is being constructed for the
* specified file. The autograder can use this to provide its own COFF
* loader, or return <tt>null</tt> to use the default loader.
*
* @param file the executable file being loaded.
* @return a loader to use in loading the file, or <tt>null</tt> to use
* the default.
*/
public Coff createLoader(OpenFile file) {
return null;
}
/**
* Request permission to send a packet. The autograder can use this to drop
* packets very selectively.
*
* @param privilege proves the authenticity of this call.
* @return <tt>true</tt> if the packet should be sent.
*/
public boolean canSendPacket(Privilege privilege) {
Lib.assertTrue(privilege == this.privilege,
"security violation");
return true;
}
/**
* Request permission to receive a packet. The autograder can use this to
* drop packets very selectively.
*
* @param privilege proves the authenticity of this call.
* @return <tt>true</tt> if the packet should be delivered to the kernel.
*/
public boolean canReceivePacket(Privilege privilege) {
Lib.assertTrue(privilege == this.privilege,
"security violation");
return true;
}
private KThread currentThread;
}