2019-02-26 08:44:17 +00:00
|
|
|
/*
|
|
|
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
|
|
|
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
|
|
|
|
* Send enquiries to dratcliffe@gmail.com
|
|
|
|
*/
|
|
|
|
|
|
|
|
package dan200.computercraft.core.computer;
|
|
|
|
|
|
|
|
import dan200.computercraft.ComputerCraft;
|
2019-03-02 02:09:14 +00:00
|
|
|
import dan200.computercraft.api.filesystem.IMount;
|
|
|
|
import dan200.computercraft.api.filesystem.IWritableMount;
|
2019-02-26 08:44:17 +00:00
|
|
|
import dan200.computercraft.api.lua.ILuaAPI;
|
|
|
|
import dan200.computercraft.api.lua.ILuaContext;
|
|
|
|
import dan200.computercraft.api.lua.LuaException;
|
|
|
|
import dan200.computercraft.core.apis.ArgumentHelper;
|
|
|
|
import dan200.computercraft.core.filesystem.MemoryMount;
|
|
|
|
import dan200.computercraft.core.terminal.Terminal;
|
|
|
|
import org.apache.logging.log4j.LogManager;
|
2019-03-01 23:48:32 +00:00
|
|
|
import org.junit.jupiter.api.Assertions;
|
2019-02-26 08:44:17 +00:00
|
|
|
|
|
|
|
import javax.annotation.Nonnull;
|
|
|
|
import javax.annotation.Nullable;
|
2019-05-30 18:36:28 +00:00
|
|
|
import java.util.Arrays;
|
2019-03-02 02:09:14 +00:00
|
|
|
import java.util.function.Consumer;
|
2019-02-26 08:44:17 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper class to run a program on a computer.
|
|
|
|
*/
|
|
|
|
public class ComputerBootstrap
|
|
|
|
{
|
|
|
|
private static final int TPS = 20;
|
|
|
|
private static final int MAX_TIME = 10;
|
|
|
|
|
2019-03-02 02:09:14 +00:00
|
|
|
public static void run( IMount mount, Consumer<Computer> setup )
|
2019-02-26 08:44:17 +00:00
|
|
|
{
|
2019-03-02 02:09:14 +00:00
|
|
|
|
2019-02-26 08:44:17 +00:00
|
|
|
}
|
|
|
|
|
2019-03-02 02:09:14 +00:00
|
|
|
public static void run( String program )
|
2019-02-26 08:44:17 +00:00
|
|
|
{
|
|
|
|
MemoryMount mount = new MemoryMount()
|
|
|
|
.addFile( "test.lua", program )
|
|
|
|
.addFile( "startup", "assertion.assert(pcall(loadfile('test.lua', _ENV))) os.shutdown()" );
|
|
|
|
|
2019-06-07 23:28:03 +00:00
|
|
|
run( mount, x -> { } );
|
2019-03-02 02:09:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static void run( IWritableMount mount, Consumer<Computer> setup )
|
|
|
|
{
|
|
|
|
ComputerCraft.logPeripheralErrors = true;
|
|
|
|
ComputerCraft.log = LogManager.getLogger( ComputerCraft.MOD_ID );
|
|
|
|
|
2019-02-26 08:44:17 +00:00
|
|
|
Terminal term = new Terminal( ComputerCraft.terminalWidth_computer, ComputerCraft.terminalHeight_computer );
|
|
|
|
final Computer computer = new Computer( new BasicEnvironment( mount ), term, 0 );
|
|
|
|
|
|
|
|
AssertApi api = new AssertApi();
|
2019-02-26 10:31:29 +00:00
|
|
|
computer.addApi( api );
|
2019-02-26 08:44:17 +00:00
|
|
|
|
2019-03-02 02:09:14 +00:00
|
|
|
setup.accept( computer );
|
|
|
|
|
2019-02-26 08:44:17 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
computer.turnOn();
|
|
|
|
boolean everOn = false;
|
|
|
|
|
|
|
|
for( int tick = 0; tick < TPS * MAX_TIME; tick++ )
|
|
|
|
{
|
|
|
|
long start = System.currentTimeMillis();
|
|
|
|
|
|
|
|
computer.tick();
|
|
|
|
MainThread.executePendingTasks();
|
|
|
|
|
|
|
|
if( api.message != null )
|
|
|
|
{
|
|
|
|
ComputerCraft.log.debug( "Shutting down due to error" );
|
|
|
|
computer.shutdown();
|
2019-03-01 23:48:32 +00:00
|
|
|
Assertions.fail( api.message );
|
2019-02-26 08:44:17 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
long remaining = (1000 / TPS) - (System.currentTimeMillis() - start);
|
|
|
|
if( remaining > 0 ) Thread.sleep( remaining );
|
|
|
|
|
|
|
|
// Break if the computer was once on, and is now off.
|
|
|
|
everOn |= computer.isOn();
|
|
|
|
if( (everOn || tick > TPS) && !computer.isOn() ) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( computer.isOn() || !api.didAssert )
|
|
|
|
{
|
2019-02-28 16:36:26 +00:00
|
|
|
StringBuilder builder = new StringBuilder().append( "Did not correctly [" );
|
2019-02-26 08:44:17 +00:00
|
|
|
if( !api.didAssert ) builder.append( " assert" );
|
|
|
|
if( computer.isOn() ) builder.append( " shutdown" );
|
2019-02-28 16:36:26 +00:00
|
|
|
builder.append( " ]\n" );
|
2019-02-26 08:44:17 +00:00
|
|
|
|
|
|
|
for( int line = 0; line < 19; line++ )
|
|
|
|
{
|
|
|
|
builder.append( String.format( "%2d | %" + term.getWidth() + "s |\n", line + 1, term.getLine( line ) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
computer.shutdown();
|
2019-03-01 23:48:32 +00:00
|
|
|
Assertions.fail( builder.toString() );
|
2019-02-26 08:44:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch( InterruptedException ignored )
|
|
|
|
{
|
|
|
|
Thread.currentThread().interrupt();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private static class AssertApi implements ILuaAPI
|
|
|
|
{
|
|
|
|
boolean didAssert;
|
|
|
|
String message;
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String[] getNames()
|
|
|
|
{
|
|
|
|
return new String[] { "assertion" };
|
|
|
|
}
|
|
|
|
|
|
|
|
@Nonnull
|
|
|
|
@Override
|
|
|
|
public String[] getMethodNames()
|
|
|
|
{
|
2019-05-30 18:36:28 +00:00
|
|
|
return new String[] { "assert", "log" };
|
2019-02-26 08:44:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Nullable
|
|
|
|
@Override
|
|
|
|
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException
|
|
|
|
{
|
|
|
|
switch( method )
|
|
|
|
{
|
|
|
|
case 0: // assert
|
|
|
|
{
|
|
|
|
didAssert = true;
|
|
|
|
|
|
|
|
Object arg = arguments.length >= 1 ? arguments[0] : null;
|
|
|
|
if( arg == null || arg == Boolean.FALSE )
|
|
|
|
{
|
|
|
|
message = ArgumentHelper.optString( arguments, 1, "Assertion failed" );
|
|
|
|
throw new LuaException( message );
|
|
|
|
}
|
|
|
|
|
|
|
|
return arguments;
|
|
|
|
}
|
2019-05-30 18:36:28 +00:00
|
|
|
case 1:
|
|
|
|
ComputerCraft.log.info( "[Computer] {}", Arrays.toString( arguments ) );
|
|
|
|
return null;
|
2019-02-26 08:44:17 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|