mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-11-16 23:04:53 +00:00
Add some tests for the new executor system
And fix a couple of bugs picked up by said tests
This commit is contained in:
parent
4b741739e8
commit
8819f2559d
@ -197,3 +197,9 @@ gradle.projectsEvaluated {
|
||||
|
||||
runClient.outputs.upToDateWhen { false }
|
||||
runServer.outputs.upToDateWhen { false }
|
||||
|
||||
test {
|
||||
testLogging {
|
||||
events "failed", "standardOut", "standardError"
|
||||
}
|
||||
}
|
||||
|
@ -44,10 +44,12 @@ public interface ILuaObject
|
||||
* for the possible values and conversion rules.
|
||||
* @return An array of objects, representing the values you wish to return to the Lua program. See
|
||||
* {@link MethodResult#of(Object...)} for the valid values and conversion rules.
|
||||
* @throws LuaException If the task could not be queued, or if the task threw an exception.
|
||||
* @throws LuaException If you throw any exception from this function, a lua error will be raised with the
|
||||
* same message as your exception. Use this to throw appropriate errors if the wrong
|
||||
* arguments are supplied to your method.
|
||||
* @throws InterruptedException If the user shuts down or reboots the computer the coroutine is suspended,
|
||||
* InterruptedException will be thrown. This exception must not be caught or
|
||||
* intercepted, or the computer will leak memory and end up in a broken state.w
|
||||
* intercepted, or the computer will leak memory and end up in a broken state.
|
||||
* @see IPeripheral#callMethod(IComputerAccess, ILuaContext, int, Object[])
|
||||
* @deprecated Use {@link #callMethod(ICallContext, int, Object[])} instead.
|
||||
*/
|
||||
@ -68,12 +70,14 @@ public interface ILuaObject
|
||||
* for the possible values and conversion rules.
|
||||
* @return The result of calling this method. Use {@link MethodResult#empty()} to return nothing or
|
||||
* {@link MethodResult#of(Object...)} to return several values.
|
||||
* @throws LuaException If the task could not be queued, or if the task threw an exception.
|
||||
* @throws LuaException If you throw any exception from this function, a lua error will be raised with the
|
||||
* same message as your exception. Use this to throw appropriate errors if the wrong
|
||||
* arguments are supplied to your method.
|
||||
* @see IPeripheral#callMethod(IComputerAccess, ICallContext, int, Object[])
|
||||
* @see MethodResult
|
||||
*/
|
||||
@Nonnull
|
||||
@SuppressWarnings({ "deprecation" })
|
||||
@SuppressWarnings( { "deprecation" } )
|
||||
default MethodResult callMethod( @Nonnull ICallContext context, int method, @Nonnull Object[] arguments ) throws LuaException
|
||||
{
|
||||
return MethodResult.withLuaContext( lua -> callMethod( lua, method, arguments ) );
|
||||
|
@ -89,16 +89,17 @@ public abstract class MethodResult
|
||||
* Normally you'll wish to consume the event using {@link #then(ILuaFunction)}. This can be done slightly more
|
||||
* easily with {@link #pullEvent(String, ILuaFunction)}.
|
||||
*
|
||||
* @param filter The event name to filter on.
|
||||
* @return The constructed method result. This evaluates to the name of the event that occurred, and any event
|
||||
* parameters.
|
||||
* @see #pullEvent(String, ILuaFunction)
|
||||
* @see #pullEvent()
|
||||
*/
|
||||
@Nonnull
|
||||
public static MethodResult pullEvent( @Nonnull String event )
|
||||
public static MethodResult pullEvent( @Nonnull String filter )
|
||||
{
|
||||
Preconditions.checkNotNull( event, "event cannot be null" );
|
||||
return new OnEvent( false, event );
|
||||
Preconditions.checkNotNull( filter, "event cannot be null" );
|
||||
return new OnEvent( false, filter );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,6 +109,7 @@ public abstract class MethodResult
|
||||
* If you want to listen to a specific event, it's easier to use {@link #pullEvent(String, ILuaFunction)} rather
|
||||
* than running until the desired event is found.
|
||||
*
|
||||
* @param callback The function to call when the event is received.
|
||||
* @return The constructed method result. This evaluates to the result of the {@code callback}.
|
||||
* @see #pullEvent()
|
||||
* @see #pullEvent(String, ILuaFunction)
|
||||
@ -123,6 +125,8 @@ public abstract class MethodResult
|
||||
* Wait for the specified event to occur on the computer, suspending the coroutine until it arises. This method to
|
||||
* {@link #pullEvent(String)} and {@link #then(ILuaFunction)}.
|
||||
*
|
||||
* @param filter The event name to filter on.
|
||||
* @param callback The function to call when the event is received.
|
||||
* @return The constructed method result. This evaluates to the result of the {@code callback}.
|
||||
* @see #pullEvent(String)
|
||||
* @see #pullEvent(ILuaFunction)
|
||||
@ -151,19 +155,21 @@ public abstract class MethodResult
|
||||
* The same as {@link #pullEvent(String)}, except {@code terminated} events are also passed to the callback, instead
|
||||
* of throwing an error. Only use this if you want to prevent program termination, which is not recommended.
|
||||
*
|
||||
* @param filter The event name to filter on.
|
||||
* @return The constructed method result. This evaluates to the name of the event that occurred, and any event
|
||||
* parameters.
|
||||
*/
|
||||
@Nonnull
|
||||
public static MethodResult pullEventRaw( @Nonnull String event )
|
||||
public static MethodResult pullEventRaw( @Nonnull String filter )
|
||||
{
|
||||
return new OnEvent( true, event );
|
||||
return new OnEvent( true, filter );
|
||||
}
|
||||
|
||||
/**
|
||||
* The same as {@link #pullEvent(ILuaFunction)}, except {@code terminated} events are also passed to the callback,
|
||||
* instead of throwing an error. Only use this if you want to prevent program termination, which is not recommended.
|
||||
*
|
||||
* @param callback The function to call when the event is received.
|
||||
* @return The constructed method result. This evaluates to the result of the {@code callback}.
|
||||
*/
|
||||
@Nonnull
|
||||
@ -178,6 +184,8 @@ public abstract class MethodResult
|
||||
* callback, instead of throwing an error. Only use this if you want to prevent program termination, which is not
|
||||
* recommended.
|
||||
*
|
||||
* @param filter The event name to filter on.
|
||||
* @param callback The function to call when the event is received.
|
||||
* @return The constructed method result. This evaluates to the result of the {@code callback}.
|
||||
*/
|
||||
@Nonnull
|
||||
@ -237,6 +245,8 @@ public abstract class MethodResult
|
||||
*
|
||||
* @param context The context to execute with.
|
||||
* @return The resulting values.
|
||||
* @throws LuaException If an error was thrown while executing one of the methods within this future.
|
||||
* @throws InterruptedException If the user shuts down or reboots the computer while the coroutine is suspended.
|
||||
* @see #withLuaContext(ILuaContextTask)
|
||||
* @deprecated This should not be used except to interface between the two call systems.
|
||||
*/
|
||||
|
@ -157,11 +157,14 @@ class CobaltLuaContext extends CobaltCallContext implements ILuaContext
|
||||
} );
|
||||
}
|
||||
|
||||
Object[] resume( LuaState state, CobaltLuaMachine machine, Object[] args ) throws LuaError, UnwindThrowable
|
||||
void resume( Object[] args )
|
||||
{
|
||||
values = args;
|
||||
resume.signal();
|
||||
}
|
||||
|
||||
Object[] await( LuaState state, CobaltLuaMachine machine ) throws LuaError, UnwindThrowable
|
||||
{
|
||||
if( !done )
|
||||
{
|
||||
try
|
||||
@ -170,14 +173,12 @@ class CobaltLuaContext extends CobaltCallContext implements ILuaContext
|
||||
}
|
||||
catch( InterruptedException e )
|
||||
{
|
||||
state.debug.onReturn();
|
||||
throw new LuaError( "Java Exception Thrown: " + e.toString(), 0 );
|
||||
}
|
||||
}
|
||||
|
||||
if( done )
|
||||
{
|
||||
state.debug.onReturn();
|
||||
if( exception != null ) throw exception;
|
||||
return values;
|
||||
}
|
||||
|
@ -235,6 +235,7 @@ public class CobaltLuaMachine implements ILuaMachine
|
||||
}
|
||||
catch( LuaError e )
|
||||
{
|
||||
if( ComputerCraft.logPeripheralErrors ) ComputerCraft.log.error( "Main thread crashed", e );
|
||||
m_mainRoutine.abandon();
|
||||
m_mainRoutine = null;
|
||||
}
|
||||
|
@ -13,8 +13,6 @@ import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.api.lua.MethodResult;
|
||||
import dan200.computercraft.core.computer.Computer;
|
||||
import org.squiddev.cobalt.*;
|
||||
import org.squiddev.cobalt.debug.DebugFrame;
|
||||
import org.squiddev.cobalt.debug.DebugHandler;
|
||||
import org.squiddev.cobalt.debug.DebugState;
|
||||
import org.squiddev.cobalt.function.VarArgFunction;
|
||||
|
||||
@ -62,12 +60,19 @@ class CobaltWrapperFunction extends VarArgFunction implements Resumable<CobaltWr
|
||||
throw new LuaError( "Java Exception Thrown: " + e.toString(), 0 );
|
||||
}
|
||||
|
||||
// Verify we've a "well formed" future
|
||||
if( future == null )
|
||||
{
|
||||
ComputerCraft.log.error( "Null result from " + delegate );
|
||||
throw new LuaError( "Java Exception Thrown: Null result" );
|
||||
}
|
||||
|
||||
// Fast path for immediate results
|
||||
if( future instanceof MethodResult.Immediate )
|
||||
{
|
||||
return machine.toValues( ((MethodResult.Immediate) future).getResult() );
|
||||
}
|
||||
|
||||
State context = new State();
|
||||
try
|
||||
{
|
||||
@ -75,12 +80,11 @@ class CobaltWrapperFunction extends VarArgFunction implements Resumable<CobaltWr
|
||||
}
|
||||
catch( UnwindThrowable e )
|
||||
{
|
||||
// Push our state onto the stack if need-be.
|
||||
DebugHandler handler = state.debug;
|
||||
DebugState ds = handler.getDebugState();
|
||||
DebugFrame di = handler.onCall( ds, this );
|
||||
di.state = context;
|
||||
|
||||
// Push our state onto the stack if need-be. Normally this wouldn't be safe and we
|
||||
// should do this at the very beginning, but we know that we won't be calling anything
|
||||
// else which will push to the resume stack.
|
||||
DebugState ds = state.debug.getDebugState();
|
||||
state.debug.onCall( ds, this, context );
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@ -88,11 +92,10 @@ class CobaltWrapperFunction extends VarArgFunction implements Resumable<CobaltWr
|
||||
@Override
|
||||
public Varargs resume( LuaState state, State context, Varargs args ) throws LuaError, UnwindThrowable
|
||||
{
|
||||
Varargs result;
|
||||
try
|
||||
{
|
||||
Varargs result = doResume( state, context, args );
|
||||
state.debug.onReturn();
|
||||
return result;
|
||||
result = doResume( state, context, args );
|
||||
}
|
||||
catch( LuaError e )
|
||||
{
|
||||
@ -104,6 +107,9 @@ class CobaltWrapperFunction extends VarArgFunction implements Resumable<CobaltWr
|
||||
state.debug.onReturn();
|
||||
throw new LuaError( e );
|
||||
}
|
||||
|
||||
state.debug.onReturn();
|
||||
return result;
|
||||
}
|
||||
|
||||
private Varargs doResume( LuaState state, State context, Varargs args ) throws LuaError, UnwindThrowable
|
||||
@ -126,7 +132,7 @@ class CobaltWrapperFunction extends VarArgFunction implements Resumable<CobaltWr
|
||||
if( args.arg( 3 ).toBoolean() )
|
||||
{
|
||||
// Extract the return values from the event and return them
|
||||
return runCallback( state, context, CobaltLuaMachine.toObjects( args, 4 ) );
|
||||
return runFuture( state, context, context.taskResult );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -142,7 +148,8 @@ class CobaltWrapperFunction extends VarArgFunction implements Resumable<CobaltWr
|
||||
}
|
||||
else if( future instanceof MethodResult.WithLuaContext )
|
||||
{
|
||||
return runCallback( state, context, context.luaContext.resume( state, machine, CobaltLuaMachine.toObjects( args, 1 ) ) );
|
||||
context.luaContext.resume( CobaltLuaMachine.toObjects( args, 1 ) );
|
||||
return runCallback( state, context, context.luaContext.await( state, machine ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -223,6 +230,7 @@ class CobaltWrapperFunction extends VarArgFunction implements Resumable<CobaltWr
|
||||
context.pending = future;
|
||||
CobaltLuaContext luaContext = context.luaContext = new CobaltLuaContext( computer, state );
|
||||
luaContext.execute( withContext.getConsumer() );
|
||||
return runCallback( state, context, luaContext.await( state, machine ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2018. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.core.computer;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.filesystem.IMount;
|
||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||
import dan200.computercraft.core.filesystem.FileMount;
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
public class FakeComputerEnvironment implements IComputerEnvironment
|
||||
{
|
||||
private final boolean colour;
|
||||
private final int id;
|
||||
|
||||
public FakeComputerEnvironment( int id, boolean colour )
|
||||
{
|
||||
this.colour = colour;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDay()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTimeOfDay()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isColour()
|
||||
{
|
||||
return colour;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int assignNewID()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWritableMount createSaveDirMount( String subPath, long capacity )
|
||||
{
|
||||
return new FileMount( new File( "computer/" + subPath ), capacity );
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMount createResourceMount( String domain, String subPath )
|
||||
{
|
||||
String fullPath = "assets/" + domain + "/" + subPath;
|
||||
URL url = ComputerCraft.class.getProtectionDomain().getCodeSource().getLocation();
|
||||
File file = new File( url.getPath(), fullPath );
|
||||
if( !file.exists() ) file = new File( "src/main/resources", fullPath );
|
||||
|
||||
if( !file.exists() ) throw new RuntimeException( "Cannot find ROM in " + file );
|
||||
|
||||
return new FileMount( file, 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream createResourceFile( String domain, String subPath )
|
||||
{
|
||||
String fullPath = "assets/" + domain + "/" + subPath;
|
||||
return ComputerCraft.class.getClassLoader().getResourceAsStream( fullPath );
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getComputerSpaceLimit()
|
||||
{
|
||||
return ComputerCraft.computerSpaceLimit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHostString()
|
||||
{
|
||||
return "ComputerCraft ${version} (Minecraft " + Loader.MC_VERSION + ")";
|
||||
}
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2018. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.core.computer;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.lua.*;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public final class RunOnComputer
|
||||
{
|
||||
public static final int STARTUP_TIMEOUT = 10;
|
||||
public static final int RUN_TIMEOUT = 100;
|
||||
|
||||
public static void run( String task ) throws Exception
|
||||
{
|
||||
run( task, x -> {
|
||||
} );
|
||||
}
|
||||
|
||||
public static void run( String task, Consumer<Computer> setup ) throws Exception
|
||||
{
|
||||
if( ComputerCraft.log == null ) ComputerCraft.log = LogManager.getLogger( "computercraft" );
|
||||
ComputerCraft.logPeripheralErrors = true;
|
||||
|
||||
// Setup computer
|
||||
Terminal terminal = new Terminal( ComputerCraft.terminalWidth_computer, ComputerCraft.terminalHeight_computer );
|
||||
Computer computer = new Computer( new FakeComputerEnvironment( 0, true ), terminal, 0 );
|
||||
|
||||
// Register APIS
|
||||
TestAPI api = new TestAPI( computer );
|
||||
computer.addAPI( api );
|
||||
setup.accept( computer );
|
||||
|
||||
// Setup the startup file
|
||||
try( OutputStream stream = computer.getRootMount().openForWrite( "startup.lua" ) )
|
||||
{
|
||||
String program = "" +
|
||||
"local function exec()\n" +
|
||||
" " + task + "\n" +
|
||||
"end\n" +
|
||||
"test.finish(pcall(exec))\n";
|
||||
stream.write( program.getBytes( StandardCharsets.UTF_8 ) );
|
||||
}
|
||||
|
||||
// Turn on
|
||||
ComputerThread.start();
|
||||
computer.turnOn();
|
||||
|
||||
// Run until shutdown or we timeout
|
||||
boolean everOn = false;
|
||||
int ticks = 0;
|
||||
do
|
||||
{
|
||||
computer.advance( 0.05 );
|
||||
MainThread.executePendingTasks();
|
||||
|
||||
Thread.sleep( 50 );
|
||||
ticks++;
|
||||
everOn |= computer.isOn();
|
||||
}
|
||||
while( (computer.isOn() || (!everOn && ticks < STARTUP_TIMEOUT)) && ticks <= RUN_TIMEOUT );
|
||||
|
||||
// If we never finished (say, startup errored) then print the terminal. Otherwise throw the error
|
||||
// where needed.
|
||||
if( !api.finished )
|
||||
{
|
||||
int height = terminal.getHeight() - 1;
|
||||
while( height >= 0 && terminal.getLine( height ).toString().trim().isEmpty() ) height--;
|
||||
for( int y = 0; y <= height; y++ )
|
||||
{
|
||||
System.out.printf( "%2d | %s\n", y + 1, terminal.getLine( y ) );
|
||||
}
|
||||
|
||||
fail( "Computer never finished" );
|
||||
}
|
||||
else if( api.error != null )
|
||||
{
|
||||
fail( api.error );
|
||||
}
|
||||
|
||||
ComputerThread.stop();
|
||||
}
|
||||
|
||||
private static class TestAPI implements ILuaAPI
|
||||
{
|
||||
private final Computer computer;
|
||||
|
||||
private boolean finished = false;
|
||||
private String error;
|
||||
|
||||
private TestAPI( Computer computer )
|
||||
{
|
||||
this.computer = computer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getNames()
|
||||
{
|
||||
return new String[]{ "test" };
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String[] getMethodNames()
|
||||
{
|
||||
return new String[]{ "log", "finish" };
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@Deprecated
|
||||
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException
|
||||
{
|
||||
return callMethod( (ICallContext) context, method, arguments ).evaluate( context );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MethodResult callMethod( @Nonnull ICallContext context, int method, @Nonnull Object[] arguments )
|
||||
{
|
||||
switch( method )
|
||||
{
|
||||
case 0:
|
||||
ComputerCraft.log.info( Objects.toString( arguments.length <= 0 ? null : arguments[0] ) );
|
||||
return MethodResult.empty();
|
||||
case 1:
|
||||
{
|
||||
if( arguments.length <= 0 || arguments[0] == null || arguments[0] == Boolean.FALSE )
|
||||
{
|
||||
error = Objects.toString( arguments.length <= 1 ? null : arguments[1] );
|
||||
}
|
||||
finished = true;
|
||||
computer.shutdown();
|
||||
return MethodResult.empty();
|
||||
}
|
||||
default:
|
||||
return MethodResult.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,243 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2018. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.core.lua;
|
||||
|
||||
import dan200.computercraft.api.lua.*;
|
||||
import dan200.computercraft.core.computer.RunOnComputer;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@RunWith( Parameterized.class )
|
||||
public class CobaltWrapperFunctionTest
|
||||
{
|
||||
@Parameterized.Parameter( 0 )
|
||||
public String name;
|
||||
|
||||
@Parameterized.Parameter( 1 )
|
||||
public String code;
|
||||
|
||||
@Parameterized.Parameters( name = "{0}" )
|
||||
public static Collection<Object[]> parameters()
|
||||
{
|
||||
return Arrays.stream( new Object[][]{
|
||||
new Object[]{ "empty", "assert(select('#', funcs.empty()) == 0)" },
|
||||
new Object[]{ "identity", "assert(select('#', funcs.identity(1, 2, 3)) == 3)" },
|
||||
|
||||
new Object[]{ "pullEvent", "os.queueEvent('test') assert(funcs.pullEvent() == 'test')" },
|
||||
new Object[]{ "pullEventTerminate", "os.queueEvent('terminate') assert(not pcall(funcs.pullEvent))" },
|
||||
|
||||
new Object[]{ "pullEventRaw", "os.queueEvent('test') assert(funcs.pullEventRaw() == 'test')" },
|
||||
new Object[]{ "pullEventRawTerminate", "os.queueEvent('terminate') assert(funcs.pullEventRaw() == 'terminate')" },
|
||||
|
||||
new Object[]{ "mainThread", "assert(funcs.mainThread() == 1)" },
|
||||
new Object[]{ "mainThreadMany", "for i = 1, 4 do assert(funcs.mainThread() == 1) end" }
|
||||
} ).collect( Collectors.toList() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests executing functions defined through the {@link MethodResult} API.
|
||||
*/
|
||||
@Test
|
||||
public void testMethodResult() throws Exception
|
||||
{
|
||||
RunOnComputer.run( code, c -> c.addAPI( new MethodResultAPI() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests executing functions defined through the {@link MethodResult} API called with the
|
||||
* {@link ILuaContext} evaluator.
|
||||
*/
|
||||
@Test
|
||||
public void testMethodResultEvaluate() throws Exception
|
||||
{
|
||||
RunOnComputer.run( code, c -> c.addAPI( new WrapperAPI( new MethodResultAPI() )
|
||||
{
|
||||
@Nullable
|
||||
@Override
|
||||
@Deprecated
|
||||
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException
|
||||
{
|
||||
return callMethod( (ICallContext) context, method, arguments ).evaluate( context );
|
||||
}
|
||||
} ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests using {@link MethodResult#then(ILuaFunction)} afterwards
|
||||
*/
|
||||
@Test
|
||||
public void testMethodResultThen() throws Exception
|
||||
{
|
||||
RunOnComputer.run( code, c -> c.addAPI( new WrapperAPI( new MethodResultAPI() ) {
|
||||
@Nonnull
|
||||
@Override
|
||||
public MethodResult callMethod( @Nonnull ICallContext context, int method, @Nonnull Object[] arguments ) throws LuaException
|
||||
{
|
||||
return super.callMethod( context, method, arguments )
|
||||
.then( x -> MethodResult.onMainThread( () -> MethodResult.of( x ).then( MethodResult::of ) ) )
|
||||
.then( MethodResult::of );
|
||||
}
|
||||
} ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests executing functions defined through the {@link ILuaContext} API.
|
||||
*/
|
||||
@Test
|
||||
public void testLuaContext() throws Exception
|
||||
{
|
||||
RunOnComputer.run( code, c -> c.addAPI( new LuaContextAPI() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests executing functions defined through the {@link ILuaContext} API called with the
|
||||
* {@link MethodResult} evaluator.
|
||||
*/
|
||||
@Test
|
||||
public void testWithLuaContext() throws Exception
|
||||
{
|
||||
RunOnComputer.run( code, c -> c.addAPI( new WrapperAPI( new LuaContextAPI() )
|
||||
{
|
||||
@Nonnull
|
||||
@Override
|
||||
@SuppressWarnings( "deprecation" )
|
||||
public MethodResult callMethod( @Nonnull ICallContext context, int method, @Nonnull Object[] arguments ) throws LuaException
|
||||
{
|
||||
return MethodResult.withLuaContext( c -> callMethod( c, method, arguments ) );
|
||||
}
|
||||
} ) );
|
||||
}
|
||||
|
||||
private static class MethodResultAPI implements ILuaAPI
|
||||
{
|
||||
@Override
|
||||
public String[] getNames()
|
||||
{
|
||||
return new String[]{ "funcs" };
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String[] getMethodNames()
|
||||
{
|
||||
return new String[]{ "empty", "identity", "pullEvent", "pullEventRaw", "mainThread" };
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@Deprecated
|
||||
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException
|
||||
{
|
||||
return callMethod( (ICallContext) context, method, arguments ).evaluate( context );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MethodResult callMethod( @Nonnull ICallContext context, int method, @Nonnull Object[] arguments )
|
||||
{
|
||||
switch( method )
|
||||
{
|
||||
case 0:
|
||||
return MethodResult.empty();
|
||||
case 1:
|
||||
return MethodResult.of( arguments );
|
||||
case 2:
|
||||
return MethodResult.pullEvent( "test" );
|
||||
case 3:
|
||||
return MethodResult.pullEventRaw( "test" );
|
||||
case 4:
|
||||
return MethodResult.onMainThread( () -> MethodResult.of( 1 ) );
|
||||
default:
|
||||
return MethodResult.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class LuaContextAPI implements ILuaAPI
|
||||
{
|
||||
@Override
|
||||
public String[] getNames()
|
||||
{
|
||||
return new String[]{ "funcs" };
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String[] getMethodNames()
|
||||
{
|
||||
return new String[]{ "empty", "identity", "pullEvent", "pullEventRaw", "mainThread" };
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@Deprecated
|
||||
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException
|
||||
{
|
||||
switch( method )
|
||||
{
|
||||
case 0:
|
||||
return null;
|
||||
case 1:
|
||||
return arguments;
|
||||
case 2:
|
||||
return context.pullEvent( "test" );
|
||||
case 3:
|
||||
return context.pullEventRaw( "test" );
|
||||
case 4:
|
||||
return context.executeMainThreadTask( () -> new Object[]{ 1 } );
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class WrapperAPI implements ILuaAPI
|
||||
{
|
||||
private final ILuaAPI api;
|
||||
|
||||
public WrapperAPI( ILuaAPI api )
|
||||
{
|
||||
this.api = api;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getNames()
|
||||
{
|
||||
return api.getNames();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String[] getMethodNames()
|
||||
{
|
||||
return api.getMethodNames();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@Deprecated
|
||||
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException
|
||||
{
|
||||
return api.callMethod( context, method, arguments );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MethodResult callMethod( @Nonnull ICallContext context, int method, @Nonnull Object[] arguments ) throws LuaException
|
||||
{
|
||||
return api.callMethod( context, method, arguments );
|
||||
}
|
||||
}
|
||||
}
|
@ -4,8 +4,9 @@ import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.lua.ICallContext;
|
||||
import dan200.computercraft.api.lua.ILuaContext;
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.api.lua.MethodResult;
|
||||
import dan200.computercraft.api.network.wired.IWiredElement;
|
||||
import dan200.computercraft.api.network.wired.IWiredNetwork;
|
||||
import dan200.computercraft.api.network.wired.IWiredNetworkChange;
|
||||
@ -249,7 +250,7 @@ public class NetworkTest
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Takes a long time to run, mostly for stress testing")
|
||||
@Ignore( "Takes a long time to run, mostly for stress testing" )
|
||||
public void testLarge()
|
||||
{
|
||||
final int BRUTE_SIZE = 16;
|
||||
@ -410,11 +411,19 @@ public class NetworkTest
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException
|
||||
@Deprecated
|
||||
public Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments )
|
||||
{
|
||||
return new Object[0];
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MethodResult callMethod( @Nonnull IComputerAccess computer, @Nonnull ICallContext context, int method, @Nonnull Object[] arguments )
|
||||
{
|
||||
return MethodResult.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals( @Nullable IPeripheral other )
|
||||
{
|
||||
@ -427,7 +436,7 @@ public class NetworkTest
|
||||
private final int size;
|
||||
private final T[] box;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings( "unchecked" )
|
||||
public Grid( int size )
|
||||
{
|
||||
this.size = size;
|
||||
|
Loading…
Reference in New Issue
Block a user