diff --git a/build.gradle b/build.gradle index fda9d433b..776871839 100644 --- a/build.gradle +++ b/build.gradle @@ -52,10 +52,6 @@ dependencies { shade 'org.squiddev:Cobalt:0.5.1-SNAPSHOT' - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0' - testImplementation 'org.junit.jupiter:junit-jupiter-params:5.7.0' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0' - modRuntime "me.shedaniel:RoughlyEnoughItems-api:5.8.9" modRuntime "me.shedaniel:RoughlyEnoughItems:5.8.9" } diff --git a/src/test/java/badhtmlparser/BadHtmlParser.java b/src/test/java/badhtmlparser/BadHtmlParser.java deleted file mode 100644 index 9e3f5241a..000000000 --- a/src/test/java/badhtmlparser/BadHtmlParser.java +++ /dev/null @@ -1,59 +0,0 @@ -package badhtmlparser; - -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.InputStreamReader; -import java.io.PrintStream; -import java.util.Iterator; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Iterators; -import com.google.common.collect.Multimap; -import com.google.common.collect.PeekingIterator; - -public class BadHtmlParser { - private static final Multimap IDS = HashMultimap.create(); - - public static void main(String[] args) throws FileNotFoundException { - BufferedReader reader = new BufferedReader(new InputStreamReader(BadHtmlParser.class.getResourceAsStream("/tags.html"))); - PeekingIterator iterator = Iterators.peekingIterator(reader.lines() - .iterator()); - while (iterator.hasNext()) { - String str = iterator.peek(); - try { - int count = Integer.parseInt(str); - iterator.next(); - write(iterator, count); - } catch (NumberFormatException e) { - write(iterator, 1); - } - } - - - System.out.println(IDS); - print("iron_ingots"); - - // todo replace dyes by hand - } - - private static void print(String val) throws FileNotFoundException { - FileOutputStream fos = new FileOutputStream("src/main/resources/data/c/tags/items/" + val + ".json"); - PrintStream stream = new PrintStream(fos); - stream.println("{\"replace\": false,\"values\":["); - Iterator iterator = IDS.get("c:" + val) - .iterator(); - while (iterator.hasNext()) { - String s = iterator.next(); - stream.printf("\"%s\"%s", s, iterator.hasNext() ? ',' : ""); - } - stream.println("]}"); - } - - private static void write(Iterator str, int entries) { - String tag = str.next(); - for (int i = 0; i < entries; i++) { - IDS.put(tag, str.next()); - } - } -} diff --git a/src/test/java/dan200/computercraft/core/ComputerTestDelegate.java b/src/test/java/dan200/computercraft/core/ComputerTestDelegate.java deleted file mode 100644 index 864629425..000000000 --- a/src/test/java/dan200/computercraft/core/ComputerTestDelegate.java +++ /dev/null @@ -1,489 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.filesystem.IWritableMount; -import dan200.computercraft.api.lua.ILuaAPI; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.core.computer.BasicEnvironment; -import dan200.computercraft.core.computer.Computer; -import dan200.computercraft.core.computer.ComputerSide; -import dan200.computercraft.core.computer.MainThread; -import dan200.computercraft.core.filesystem.FileMount; -import dan200.computercraft.core.filesystem.FileSystemException; -import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.shared.peripheral.modem.ModemState; -import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemPeripheral; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.junit.jupiter.api.*; -import org.junit.jupiter.api.function.Executable; -import org.opentest4j.AssertionFailedError; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.io.BufferedWriter; -import java.io.File; -import java.io.IOException; -import java.io.Writer; -import java.nio.channels.Channels; -import java.nio.channels.WritableByteChannel; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.util.*; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.ReentrantLock; -import java.util.stream.Stream; - -import static dan200.computercraft.api.lua.LuaValues.getType; - -/** - * Loads tests from {@code test-rom/spec} and executes them. - * - * This spins up a new computer and runs the {@code mcfly.lua} script. This will then load all files in the {@code spec} - * directory and register them with {@code cct_test.start}. - * - * From the test names, we generate a tree of {@link DynamicNode}s which queue an event and wait for - * {@code cct_test.submit} to be called. McFly pulls these events, executes the tests and then calls the submit method. - * - * Once all tests are done, we invoke {@code cct_test.finish} in order to mark everything as complete. - */ -public class ComputerTestDelegate -{ - private static final File REPORT_PATH = new File( "test-files/luacov.report.out" ); - - private static final Logger LOG = LogManager.getLogger( ComputerTestDelegate.class ); - - private static final long TICK_TIME = TimeUnit.MILLISECONDS.toNanos( 50 ); - - private static final long TIMEOUT = TimeUnit.SECONDS.toNanos( 10 ); - - private final ReentrantLock lock = new ReentrantLock(); - private Computer computer; - - private final Condition hasTests = lock.newCondition(); - private DynamicNodeBuilder tests; - - private final Condition hasRun = lock.newCondition(); - private String currentTest; - private boolean runFinished; - private Throwable runResult; - - private final Condition hasFinished = lock.newCondition(); - private boolean finished = false; - private Map> finishedWith; - - @BeforeEach - public void before() throws IOException - { - ComputerCraft.logPeripheralErrors = true; - - if( REPORT_PATH.delete() ) ComputerCraft.log.info( "Deleted previous coverage report." ); - - Terminal term = new Terminal( 78, 20 ); - IWritableMount mount = new FileMount( new File( "test-files/mount" ), 10_000_000 ); - - // Remove any existing files - List children = new ArrayList<>(); - mount.list( "", children ); - for( String child : children ) mount.delete( child ); - - // And add our startup file - try( WritableByteChannel channel = mount.openForWrite( "startup.lua" ); - Writer writer = Channels.newWriter( channel, StandardCharsets.UTF_8.newEncoder(), -1 ) ) - { - writer.write( "loadfile('test-rom/mcfly.lua', nil, _ENV)('test-rom/spec') cct_test.finish()" ); - } - - computer = new Computer( new BasicEnvironment( mount ), term, 0 ); - computer.getEnvironment().setPeripheral( ComputerSide.TOP, new FakeModem() ); - computer.addApi( new CctTestAPI() ); - - computer.turnOn(); - } - - @AfterEach - public void after() throws InterruptedException, IOException - { - try - { - LOG.info( "Finished execution" ); - computer.queueEvent( "cct_test_run", null ); - - // Wait for test execution to fully finish - lock.lockInterruptibly(); - try - { - long remaining = TIMEOUT; - while( remaining > 0 && !finished ) - { - tick(); - if( hasFinished.awaitNanos( TICK_TIME ) > 0 ) break; - remaining -= TICK_TIME; - } - - if( remaining <= 0 ) throw new IllegalStateException( "Timed out waiting for finish." + dump() ); - if( !finished ) throw new IllegalStateException( "Computer did not finish." + dump() ); - } - finally - { - lock.unlock(); - } - } - finally - { - // Show a dump of computer output - System.out.println( dump() ); - - // And shutdown - computer.shutdown(); - } - - if( finishedWith != null ) - { - REPORT_PATH.getParentFile().mkdirs(); - try( BufferedWriter writer = Files.newBufferedWriter( REPORT_PATH.toPath() ) ) - { - // new LuaCoverage( finishedWith ).write( writer ); - } - } - } - - @TestFactory - public Stream get() throws InterruptedException - { - lock.lockInterruptibly(); - try - { - long remaining = TIMEOUT; - while( remaining > 0 & tests == null ) - { - tick(); - if( hasTests.awaitNanos( TICK_TIME ) > 0 ) break; - remaining -= TICK_TIME; - } - - if( remaining <= 0 ) throw new IllegalStateException( "Timed out waiting for tests. " + dump() ); - if( tests == null ) throw new IllegalStateException( "Computer did not provide any tests. " + dump() ); - } - finally - { - lock.unlock(); - } - - return tests.buildChildren(); - } - - private static class DynamicNodeBuilder - { - private final String name; - private final Map children; - private final Executable executor; - - DynamicNodeBuilder( String name ) - { - this.name = name; - this.children = new HashMap<>(); - this.executor = null; - } - - DynamicNodeBuilder( String name, Executable executor ) - { - this.name = name; - this.children = Collections.emptyMap(); - this.executor = executor; - } - - DynamicNodeBuilder get( String name ) - { - DynamicNodeBuilder child = children.get( name ); - if( child == null ) children.put( name, child = new DynamicNodeBuilder( name ) ); - return child; - } - - void runs( String name, Executable executor ) - { - DynamicNodeBuilder child = children.get( name ); - int id = 0; - while( child != null ) - { - id++; - String subName = name + "_" + id; - child = children.get( subName ); - } - - children.put( name, new DynamicNodeBuilder( name, executor ) ); - } - - DynamicNode build() - { - return executor == null - ? DynamicContainer.dynamicContainer( name, buildChildren() ) - : DynamicTest.dynamicTest( name, executor ); - } - - Stream buildChildren() - { - return children.values().stream().map( DynamicNodeBuilder::build ); - } - } - - private String dump() - { - if( !computer.isOn() ) return "Computer is currently off."; - - Terminal term = computer.getAPIEnvironment().getTerminal(); - StringBuilder builder = new StringBuilder().append( "Computer is currently on.\n" ); - - for( int line = 0; line < term.getHeight(); line++ ) - { - builder.append( String.format( "%2d | %" + term.getWidth() + "s |\n", line + 1, term.getLine( line ) ) ); - } - - computer.shutdown(); - return builder.toString(); - } - - private void tick() - { - computer.tick(); - MainThread.executePendingTasks(); - } - - private static String formatName( String name ) - { - return name.replace( "\0", " -> " ); - } - - private static class FakeModem extends WirelessModemPeripheral - { - FakeModem() - { - super( new ModemState(), true ); - } - - @Nonnull - @Override - @SuppressWarnings( "ConstantConditions" ) - public World getWorld() - { - return null; - } - - @Nonnull - @Override - public Vec3d getPosition() - { - return Vec3d.ZERO; - } - - @Override - public boolean equals( @Nullable IPeripheral other ) - { - return this == other; - } - } - - public class CctTestAPI implements ILuaAPI - { - @Override - public String[] getNames() - { - return new String[] { "cct_test" }; - } - - @Override - public void startup() - { - try - { - computer.getAPIEnvironment().getFileSystem().mount( - "test-rom", "test-rom", - BasicEnvironment.createMount( ComputerTestDelegate.class, "test-rom", "test" ) - ); - } - catch( FileSystemException e ) - { - throw new IllegalStateException( e ); - } - } - - @LuaFunction - public final void start( Map tests ) throws LuaException - { - // Submit several tests and signal for #get to run - LOG.info( "Received tests from computer" ); - DynamicNodeBuilder root = new DynamicNodeBuilder( "" ); - for( Object key : tests.keySet() ) - { - if( !(key instanceof String) ) throw new LuaException( "Non-key string " + getType( key ) ); - - String name = (String) key; - String[] parts = name.split( "\0" ); - DynamicNodeBuilder builder = root; - for( int i = 0; i < parts.length - 1; i++ ) builder = builder.get( parts[i] ); - builder.runs( parts[parts.length - 1], () -> { - // Run it - lock.lockInterruptibly(); - try - { - // Set the current test - runResult = null; - runFinished = false; - currentTest = name; - - // Tell the computer to run it - LOG.info( "Starting '{}'", formatName( name ) ); - computer.queueEvent( "cct_test_run", new Object[] { name } ); - - long remaining = TIMEOUT; - while( remaining > 0 && computer.isOn() && !runFinished ) - { - tick(); - - long waiting = hasRun.awaitNanos( TICK_TIME ); - if( waiting > 0 ) break; - remaining -= TICK_TIME; - } - - LOG.info( "Finished '{}'", formatName( name ) ); - - if( remaining <= 0 ) - { - throw new IllegalStateException( "Timed out waiting for test" ); - } - else if( !computer.isOn() ) - { - throw new IllegalStateException( "Computer turned off mid-execution" ); - } - - if( runResult != null ) throw runResult; - } - finally - { - lock.unlock(); - currentTest = null; - } - } ); - } - - try - { - lock.lockInterruptibly(); - } - catch( InterruptedException e ) - { - throw new RuntimeException( e ); - } - try - { - ComputerTestDelegate.this.tests = root; - hasTests.signal(); - } - finally - { - lock.unlock(); - } - } - - @LuaFunction - public final void submit( Map tbl ) - { - // Submit the result of a test, allowing the test executor to continue - String name = (String) tbl.get( "name" ); - if( name == null ) - { - ComputerCraft.log.error( "Oh no: {}", tbl ); - } - String status = (String) tbl.get( "status" ); - String message = (String) tbl.get( "message" ); - String trace = (String) tbl.get( "trace" ); - - StringBuilder wholeMessage = new StringBuilder(); - if( message != null ) wholeMessage.append( message ); - if( trace != null ) - { - if( wholeMessage.length() != 0 ) wholeMessage.append( '\n' ); - wholeMessage.append( trace ); - } - - try - { - lock.lockInterruptibly(); - } - catch( InterruptedException e ) - { - throw new RuntimeException( e ); - } - try - { - LOG.info( "'{}' finished with {}", formatName( name ), status ); - - // Skip if a test mismatch - if( !name.equals( currentTest ) ) - { - LOG.warn( "Skipping test '{}', as we're currently executing '{}'", formatName( name ), formatName( currentTest ) ); - return; - } - - switch( status ) - { - case "ok": - case "pending": - break; - case "fail": - runResult = new AssertionFailedError( wholeMessage.toString() ); - break; - case "error": - runResult = new IllegalStateException( wholeMessage.toString() ); - break; - } - - runFinished = true; - hasRun.signal(); - } - finally - { - lock.unlock(); - } - } - - @LuaFunction - public final void finish( Optional> result ) - { - @SuppressWarnings( "unchecked" ) - Map> finishedResult = (Map>) result.orElse( null ); - LOG.info( "Finished" ); - - // Signal to after that execution has finished - try - { - lock.lockInterruptibly(); - } - catch( InterruptedException e ) - { - throw new RuntimeException( e ); - } - try - { - finished = true; - if( finishedResult != null ) finishedWith = finishedResult; - - hasFinished.signal(); - } - finally - { - lock.unlock(); - } - } - } -} diff --git a/src/test/java/dan200/computercraft/core/apis/ObjectWrapper.java b/src/test/java/dan200/computercraft/core/apis/ObjectWrapper.java deleted file mode 100644 index 1c50dc779..000000000 --- a/src/test/java/dan200/computercraft/core/apis/ObjectWrapper.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis; - -import dan200.computercraft.api.lua.*; -import dan200.computercraft.core.asm.LuaMethod; -import dan200.computercraft.core.asm.NamedMethod; - -import javax.annotation.Nonnull; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -public class ObjectWrapper implements ILuaContext -{ - private final Object object; - private final Map methodMap; - - public ObjectWrapper( Object object ) - { - this.object = object; - String[] dynamicMethods = object instanceof IDynamicLuaObject - ? Objects.requireNonNull( ((IDynamicLuaObject) object).getMethodNames(), "Methods cannot be null" ) - : LuaMethod.EMPTY_METHODS; - - List> methods = LuaMethod.GENERATOR.getMethods( object.getClass() ); - - Map methodMap = this.methodMap = new HashMap<>( methods.size() + dynamicMethods.length ); - for( int i = 0; i < dynamicMethods.length; i++ ) - { - methodMap.put( dynamicMethods[i], LuaMethod.DYNAMIC.get( i ) ); - } - for( NamedMethod method : methods ) - { - methodMap.put( method.getName(), method.getMethod() ); - } - } - - public Object[] call( String name, Object... args ) throws LuaException - { - LuaMethod method = methodMap.get( name ); - if( method == null ) throw new IllegalStateException( "No such method '" + name + "'" ); - - return method.apply( object, this, new ObjectArguments( args ) ).getResult(); - } - - @SuppressWarnings( "unchecked" ) - public T callOf( String name, Object... args ) throws LuaException - { - return (T) call( name, args )[0]; - } - - public T callOf( Class klass, String name, Object... args ) throws LuaException - { - return klass.cast( call( name, args )[0] ); - } - - @Override - public long issueMainThreadTask( @Nonnull ILuaTask task ) - { - throw new IllegalStateException( "Method should never queue events" ); - } -} diff --git a/src/test/java/dan200/computercraft/core/apis/handles/BinaryReadableHandleTest.java b/src/test/java/dan200/computercraft/core/apis/handles/BinaryReadableHandleTest.java deleted file mode 100644 index eacd23a41..000000000 --- a/src/test/java/dan200/computercraft/core/apis/handles/BinaryReadableHandleTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.handles; - -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.core.apis.ObjectWrapper; -import org.junit.jupiter.api.Test; - -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; - -import static org.junit.jupiter.api.Assertions.*; - -public class BinaryReadableHandleTest -{ - @Test - public void testReadChar() throws LuaException - { - ObjectWrapper wrapper = fromLength( 5 ); - assertEquals( 'A', (int) wrapper.callOf( Integer.class, "read" ) ); - } - - @Test - public void testReadShortComplete() throws LuaException - { - ObjectWrapper wrapper = fromLength( 10 ); - assertEquals( 5, wrapper.callOf( "read", 5 ).remaining() ); - } - - @Test - public void testReadShortPartial() throws LuaException - { - ObjectWrapper wrapper = fromLength( 5 ); - assertEquals( 5, wrapper.callOf( "read", 10 ).remaining() ); - } - - @Test - public void testReadLongComplete() throws LuaException - { - ObjectWrapper wrapper = fromLength( 10000 ); - assertEquals( 9000, wrapper.callOf( "read", 9000 ).length ); - } - - @Test - public void testReadLongPartial() throws LuaException - { - ObjectWrapper wrapper = fromLength( 10000 ); - assertEquals( 10000, wrapper.callOf( "read", 11000 ).length ); - } - - @Test - public void testReadLongPartialSmaller() throws LuaException - { - ObjectWrapper wrapper = fromLength( 1000 ); - assertEquals( 1000, wrapper.callOf( "read", 11000 ).remaining() ); - } - - @Test - public void testReadLine() throws LuaException - { - ObjectWrapper wrapper = new ObjectWrapper( BinaryReadableHandle.of( new ArrayByteChannel( "hello\r\nworld\r!".getBytes( StandardCharsets.UTF_8 ) ) ) ); - assertArrayEquals( "hello".getBytes( StandardCharsets.UTF_8 ), wrapper.callOf( "readLine" ) ); - assertArrayEquals( "world\r!".getBytes( StandardCharsets.UTF_8 ), wrapper.callOf( "readLine" ) ); - assertNull( wrapper.call( "readLine" ) ); - } - - @Test - public void testReadLineTrailing() throws LuaException - { - ObjectWrapper wrapper = new ObjectWrapper( BinaryReadableHandle.of( new ArrayByteChannel( "hello\r\nworld\r!".getBytes( StandardCharsets.UTF_8 ) ) ) ); - assertArrayEquals( "hello\r\n".getBytes( StandardCharsets.UTF_8 ), wrapper.callOf( "readLine", true ) ); - assertArrayEquals( "world\r!".getBytes( StandardCharsets.UTF_8 ), wrapper.callOf( "readLine", true ) ); - assertNull( wrapper.call( "readLine", true ) ); - } - - private static ObjectWrapper fromLength( int length ) - { - byte[] input = new byte[length]; - Arrays.fill( input, (byte) 'A' ); - return new ObjectWrapper( BinaryReadableHandle.of( new ArrayByteChannel( input ) ) ); - } -} diff --git a/src/test/java/dan200/computercraft/core/apis/handles/EncodedReadableHandleTest.java b/src/test/java/dan200/computercraft/core/apis/handles/EncodedReadableHandleTest.java deleted file mode 100644 index 8937d2588..000000000 --- a/src/test/java/dan200/computercraft/core/apis/handles/EncodedReadableHandleTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.handles; - -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.core.apis.ObjectWrapper; -import org.junit.jupiter.api.Test; - -import java.io.BufferedReader; -import java.io.CharArrayReader; -import java.util.Arrays; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class EncodedReadableHandleTest -{ - @Test - public void testReadChar() throws LuaException - { - ObjectWrapper wrapper = fromLength( 5 ); - assertEquals( "A", wrapper.callOf( "read" ) ); - } - - @Test - public void testReadShortComplete() throws LuaException - { - ObjectWrapper wrapper = fromLength( 10 ); - assertEquals( "AAAAA", wrapper.callOf( "read", 5 ) ); - } - - @Test - public void testReadShortPartial() throws LuaException - { - ObjectWrapper wrapper = fromLength( 5 ); - assertEquals( "AAAAA", wrapper.callOf( "read", 10 ) ); - } - - - @Test - public void testReadLongComplete() throws LuaException - { - ObjectWrapper wrapper = fromLength( 10000 ); - assertEquals( 9000, wrapper.callOf( "read", 9000 ).length() ); - } - - @Test - public void testReadLongPartial() throws LuaException - { - ObjectWrapper wrapper = fromLength( 10000 ); - assertEquals( 10000, wrapper.callOf( "read", 11000 ).length() ); - } - - @Test - public void testReadLongPartialSmaller() throws LuaException - { - ObjectWrapper wrapper = fromLength( 1000 ); - assertEquals( 1000, wrapper.callOf( "read", 11000 ).length() ); - } - - private static ObjectWrapper fromLength( int length ) - { - char[] input = new char[length]; - Arrays.fill( input, 'A' ); - return new ObjectWrapper( new EncodedReadableHandle( new BufferedReader( new CharArrayReader( input ) ) ) ); - } -} diff --git a/src/test/java/dan200/computercraft/core/apis/options/AddressRuleTest.java b/src/test/java/dan200/computercraft/core/apis/options/AddressRuleTest.java deleted file mode 100644 index 0e647ed17..000000000 --- a/src/test/java/dan200/computercraft/core/apis/options/AddressRuleTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.http.options; - -import org.junit.jupiter.api.Test; - -import java.net.InetSocketAddress; -import java.util.Collections; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class AddressRuleTest -{ - @Test - public void matchesPort() - { - Iterable rules = Collections.singletonList( AddressRule.parse( - "127.0.0.1", 8080, - new PartialOptions( Action.ALLOW, null, null, null, null ) - ) ); - - assertEquals( apply( rules, "localhost", 8080 ).action, Action.ALLOW ); - assertEquals( apply( rules, "localhost", 8081 ).action, Action.DENY ); - } - - private Options apply( Iterable rules, String host, int port ) - { - return AddressRule.apply( rules, host, new InetSocketAddress( host, port ) ); - } -} diff --git a/src/test/java/dan200/computercraft/core/computer/BasicEnvironment.java b/src/test/java/dan200/computercraft/core/computer/BasicEnvironment.java deleted file mode 100644 index a96e312be..000000000 --- a/src/test/java/dan200/computercraft/core/computer/BasicEnvironment.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. 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 dan200.computercraft.core.filesystem.JarMount; -import dan200.computercraft.core.filesystem.MemoryMount; - -import javax.annotation.Nonnull; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.URL; - -/** - * A very basic environment. - */ -public class BasicEnvironment implements IComputerEnvironment -{ - private final IWritableMount mount; - - public BasicEnvironment() - { - this( new MemoryMount() ); - } - - public BasicEnvironment( IWritableMount mount ) - { - this.mount = mount; - } - - @Override - public int assignNewID() - { - return 0; - } - - @Override - public IWritableMount createSaveDirMount( String path, long space ) - { - return mount; - } - - @Override - public int getDay() - { - return 0; - } - - @Override - public double getTimeOfDay() - { - return 0; - } - - @Override - public boolean isColour() - { - return true; - } - - @Override - public long getComputerSpaceLimit() - { - return ComputerCraft.computerSpaceLimit; - } - - @Nonnull - @Override - public String getHostString() - { - return "ComputerCraft 1.0 (Test environment)"; - } - - @Nonnull - @Override - public String getUserAgent() - { - return "ComputerCraft/1.0"; - } - - @Override - public IMount createResourceMount( String domain, String subPath ) - { - return createMount( ComputerCraft.class, "data/" + domain + "/" + subPath, "main" ); - } - - @Override - public InputStream createResourceFile( String domain, String subPath ) - { - return ComputerCraft.class.getClassLoader().getResourceAsStream( "data/" + domain + "/" + subPath ); - } - - public static IMount createMount( Class klass, String path, String fallback ) - { - File file = getContainingFile( klass ); - - if( file.isFile() ) - { - try - { - return new JarMount( file, path ); - } - catch( IOException e ) - { - throw new UncheckedIOException( e ); - } - } - else - { - File wholeFile = new File( file, path ); - - // If we don't exist, walk up the tree looking for resource folders - File baseFile = file; - while( baseFile != null && !wholeFile.exists() ) - { - baseFile = baseFile.getParentFile(); - wholeFile = new File( baseFile, "src/" + fallback + "/resources/" + path ); - } - - if( !wholeFile.exists() ) throw new IllegalStateException( "Cannot find ROM mount at " + file ); - - return new FileMount( wholeFile, 0 ); - } - } - - - private static File getContainingFile( Class klass ) - { - String path = klass.getProtectionDomain().getCodeSource().getLocation().getPath(); - int bangIndex = path.indexOf( "!" ); - - // Plain old file, so step up from dan200.computercraft. - if( bangIndex < 0 ) return new File( path ); - - path = path.substring( 0, bangIndex ); - URL url; - try - { - url = new URL( path ); - } - catch( MalformedURLException e ) - { - throw new IllegalStateException( e ); - } - - try - { - return new File( url.toURI() ); - } - catch( URISyntaxException e ) - { - return new File( url.getPath() ); - } - } -} diff --git a/src/test/java/dan200/computercraft/core/computer/ComputerBootstrap.java b/src/test/java/dan200/computercraft/core/computer/ComputerBootstrap.java deleted file mode 100644 index 924bc0286..000000000 --- a/src/test/java/dan200/computercraft/core/computer/ComputerBootstrap.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. 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.IWritableMount; -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.ILuaAPI; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.core.filesystem.MemoryMount; -import dan200.computercraft.core.terminal.Terminal; -import org.junit.jupiter.api.Assertions; - -import java.util.Arrays; -import java.util.function.Consumer; - -/** - * Helper class to run a program on a computer. - */ -public class ComputerBootstrap -{ - private static final int TPS = 20; - public static final int MAX_TIME = 10; - - public static void run( String program, Consumer setup, int maxTimes ) - { - MemoryMount mount = new MemoryMount() - .addFile( "test.lua", program ) - .addFile( "startup.lua", "assertion.assert(pcall(loadfile('test.lua', nil, _ENV))) os.shutdown()" ); - - run( mount, setup, maxTimes ); - } - - public static void run( String program, int maxTimes ) - { - run( program, x -> { }, maxTimes ); - } - - public static void run( IWritableMount mount, Consumer setup, int maxTicks ) - { - ComputerCraft.logPeripheralErrors = true; - ComputerCraft.maxMainComputerTime = ComputerCraft.maxMainGlobalTime = Integer.MAX_VALUE; - - Terminal term = new Terminal( ComputerCraft.terminalWidth_computer, ComputerCraft.terminalHeight_computer ); - final Computer computer = new Computer( new BasicEnvironment( mount ), term, 0 ); - - AssertApi api = new AssertApi(); - computer.addApi( api ); - - setup.accept( computer ); - - try - { - computer.turnOn(); - boolean everOn = false; - - for( int tick = 0; tick < TPS * maxTicks; tick++ ) - { - long start = System.currentTimeMillis(); - - computer.tick(); - MainThread.executePendingTasks(); - - if( api.message != null ) - { - ComputerCraft.log.debug( "Shutting down due to error" ); - computer.shutdown(); - Assertions.fail( api.message ); - 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 ) - { - StringBuilder builder = new StringBuilder().append( "Did not correctly [" ); - if( !api.didAssert ) builder.append( " assert" ); - if( computer.isOn() ) builder.append( " shutdown" ); - builder.append( " ]\n" ); - - for( int line = 0; line < 19; line++ ) - { - builder.append( String.format( "%2d | %" + term.getWidth() + "s |\n", line + 1, term.getLine( line ) ) ); - } - - computer.shutdown(); - Assertions.fail( builder.toString() ); - } - } - catch( InterruptedException ignored ) - { - Thread.currentThread().interrupt(); - } - } - - public static class AssertApi implements ILuaAPI - { - boolean didAssert; - String message; - - @Override - public String[] getNames() - { - return new String[] { "assertion" }; - } - - @LuaFunction - public final void log( IArguments arguments ) - { - ComputerCraft.log.info( "[Computer] {}", Arrays.toString( arguments.getAll() ) ); - } - - @LuaFunction( "assert" ) - public final Object[] doAssert( IArguments arguments ) throws LuaException - { - didAssert = true; - - Object arg = arguments.get( 0 ); - if( arg == null || arg == Boolean.FALSE ) - { - message = arguments.optString( 1, "Assertion failed" ); - throw new LuaException( message ); - } - - return arguments.getAll(); - } - } -} diff --git a/src/test/java/dan200/computercraft/core/computer/ComputerTest.java b/src/test/java/dan200/computercraft/core/computer/ComputerTest.java deleted file mode 100644 index d25458310..000000000 --- a/src/test/java/dan200/computercraft/core/computer/ComputerTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.computer; - -import com.google.common.io.CharStreams; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.Objects; - -import static java.time.Duration.ofSeconds; -import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; - -public class ComputerTest -{ - @Test - public void testTimeout() - { - assertTimeoutPreemptively( ofSeconds( 20 ), () -> { - try - { - ComputerBootstrap.run( "print('Hello') while true do end", ComputerBootstrap.MAX_TIME ); - } - catch( AssertionError e ) - { - if( e.getMessage().equals( "test.lua:1: Too long without yielding" ) ) return; - throw e; - } - - Assertions.fail( "Expected computer to timeout" ); - } ); - } - - public static void main( String[] args ) throws Exception - { - InputStream stream = ComputerTest.class.getClassLoader().getResourceAsStream( "benchmark.lua" ); - try( InputStreamReader reader = new InputStreamReader( Objects.requireNonNull( stream ), StandardCharsets.UTF_8 ) ) - { - String contents = CharStreams.toString( reader ); - ComputerBootstrap.run( contents, 1000 ); - } - } -} diff --git a/src/test/java/dan200/computercraft/core/filesystem/FileSystemTest.java b/src/test/java/dan200/computercraft/core/filesystem/FileSystemTest.java deleted file mode 100644 index 6d4e52278..000000000 --- a/src/test/java/dan200/computercraft/core/filesystem/FileSystemTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.filesystem; - -import com.google.common.io.Files; -import dan200.computercraft.api.filesystem.IWritableMount; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.core.apis.ObjectWrapper; -import dan200.computercraft.core.apis.handles.EncodedWritableHandle; -import org.junit.jupiter.api.Test; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -public class FileSystemTest -{ - private static final File ROOT = new File( "test-files/filesystem" ); - private static final long CAPACITY = 1000000; - - private static FileSystem mkFs() throws FileSystemException - { - IWritableMount writableMount = new FileMount( ROOT, CAPACITY ); - return new FileSystem( "hdd", writableMount ); - - } - - /** - * Ensures writing a file truncates it. - * - * @throws FileSystemException When the file system cannot be constructed. - * @throws LuaException When Lua functions fail. - * @throws IOException When reading and writing from strings - */ - @Test - public void testWriteTruncates() throws FileSystemException, LuaException, IOException - { - FileSystem fs = mkFs(); - - { - FileSystemWrapper writer = fs.openForWrite( "out.txt", false, EncodedWritableHandle::openUtf8 ); - ObjectWrapper wrapper = new ObjectWrapper( new EncodedWritableHandle( writer.get(), writer ) ); - wrapper.call( "write", "This is a long line" ); - wrapper.call( "close" ); - } - - assertEquals( "This is a long line", Files.asCharSource( new File( ROOT, "out.txt" ), StandardCharsets.UTF_8 ).read() ); - - { - FileSystemWrapper writer = fs.openForWrite( "out.txt", false, EncodedWritableHandle::openUtf8 ); - ObjectWrapper wrapper = new ObjectWrapper( new EncodedWritableHandle( writer.get(), writer ) ); - wrapper.call( "write", "Tiny line" ); - wrapper.call( "close" ); - } - - assertEquals( "Tiny line", Files.asCharSource( new File( ROOT, "out.txt" ), StandardCharsets.UTF_8 ).read() ); - } - - @Test - public void testUnmountCloses() throws FileSystemException - { - FileSystem fs = mkFs(); - IWritableMount mount = new FileMount( new File( ROOT, "child" ), CAPACITY ); - fs.mountWritable( "disk", "disk", mount ); - - FileSystemWrapper writer = fs.openForWrite( "disk/out.txt", false, EncodedWritableHandle::openUtf8 ); - ObjectWrapper wrapper = new ObjectWrapper( new EncodedWritableHandle( writer.get(), writer ) ); - - fs.unmount( "disk" ); - - LuaException err = assertThrows( LuaException.class, () -> wrapper.call( "write", "Tiny line" ) ); - assertEquals( "attempt to use a closed file", err.getMessage() ); - } -} diff --git a/src/test/java/dan200/computercraft/core/filesystem/JarMountTest.java b/src/test/java/dan200/computercraft/core/filesystem/JarMountTest.java deleted file mode 100644 index 7d78b0217..000000000 --- a/src/test/java/dan200/computercraft/core/filesystem/JarMountTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.filesystem; - -import com.google.common.io.ByteStreams; -import dan200.computercraft.api.filesystem.IMount; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.nio.charset.StandardCharsets; -import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.attribute.FileTime; -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import static org.junit.jupiter.api.Assertions.*; - -public class JarMountTest -{ - private static final File ZIP_FILE = new File( "test-files/jar-mount.zip" ); - - private static final FileTime MODIFY_TIME = FileTime.from( Instant.EPOCH.plus( 2, ChronoUnit.DAYS ) ); - - @BeforeAll - public static void before() throws IOException - { - ZIP_FILE.getParentFile().mkdirs(); - - try( ZipOutputStream stream = new ZipOutputStream( new FileOutputStream( ZIP_FILE ) ) ) - { - stream.putNextEntry( new ZipEntry( "dir/" ) ); - stream.closeEntry(); - - stream.putNextEntry( new ZipEntry( "dir/file.lua" ).setLastModifiedTime( MODIFY_TIME ) ); - stream.write( "print('testing')".getBytes( StandardCharsets.UTF_8 ) ); - stream.closeEntry(); - } - } - - @Test - public void mountsDir() throws IOException - { - IMount mount = new JarMount( ZIP_FILE, "dir" ); - assertTrue( mount.isDirectory( "" ), "Root should be directory" ); - assertTrue( mount.exists( "file.lua" ), "File should exist" ); - } - - @Test - public void mountsFile() throws IOException - { - IMount mount = new JarMount( ZIP_FILE, "dir/file.lua" ); - assertTrue( mount.exists( "" ), "Root should exist" ); - assertFalse( mount.isDirectory( "" ), "Root should be a file" ); - } - - @Test - public void opensFileFromFile() throws IOException - { - IMount mount = new JarMount( ZIP_FILE, "dir/file.lua" ); - byte[] contents; - try( ReadableByteChannel stream = mount.openForRead( "" ) ) - { - contents = ByteStreams.toByteArray( Channels.newInputStream( stream ) ); - } - - assertEquals( new String( contents, StandardCharsets.UTF_8 ), "print('testing')" ); - } - - @Test - public void opensFileFromDir() throws IOException - { - IMount mount = new JarMount( ZIP_FILE, "dir" ); - byte[] contents; - try( ReadableByteChannel stream = mount.openForRead( "file.lua" ) ) - { - contents = ByteStreams.toByteArray( Channels.newInputStream( stream ) ); - } - - assertEquals( new String( contents, StandardCharsets.UTF_8 ), "print('testing')" ); - } - - @Test - public void fileAttributes() throws IOException - { - BasicFileAttributes attributes = new JarMount( ZIP_FILE, "dir" ).getAttributes( "file.lua" ); - assertFalse( attributes.isDirectory() ); - assertEquals( "print('testing')".length(), attributes.size() ); - assertEquals( MODIFY_TIME, attributes.lastModifiedTime() ); - } - - @Test - public void directoryAttributes() throws IOException - { - BasicFileAttributes attributes = new JarMount( ZIP_FILE, "dir" ).getAttributes( "" ); - assertTrue( attributes.isDirectory() ); - assertEquals( 0, attributes.size() ); - } -} diff --git a/src/test/java/dan200/computercraft/core/filesystem/MemoryMount.java b/src/test/java/dan200/computercraft/core/filesystem/MemoryMount.java deleted file mode 100644 index b2cce2d44..000000000 --- a/src/test/java/dan200/computercraft/core/filesystem/MemoryMount.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.filesystem; - -import dan200.computercraft.api.filesystem.IWritableMount; -import dan200.computercraft.core.apis.handles.ArrayByteChannel; - -import javax.annotation.Nonnull; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.WritableByteChannel; -import java.util.*; - -/** - * In-memory file mounts. - */ -public class MemoryMount implements IWritableMount -{ - private final Map files = new HashMap<>(); - private final Set directories = new HashSet<>(); - - public MemoryMount() - { - directories.add( "" ); - } - - - @Override - public void makeDirectory( @Nonnull String path ) - { - File file = new File( path ); - while( file != null ) - { - directories.add( file.getPath() ); - file = file.getParentFile(); - } - } - - @Override - public void delete( @Nonnull String path ) - { - if( files.containsKey( path ) ) - { - files.remove( path ); - } - else - { - directories.remove( path ); - for( String file : files.keySet().toArray( new String[0] ) ) - { - if( file.startsWith( path ) ) - { - files.remove( file ); - } - } - - File parent = new File( path ).getParentFile(); - if( parent != null ) delete( parent.getPath() ); - } - } - - @Nonnull - @Override - public WritableByteChannel openForWrite( @Nonnull final String path ) - { - return Channels.newChannel( new ByteArrayOutputStream() - { - @Override - public void close() throws IOException - { - super.close(); - files.put( path, toByteArray() ); - } - } ); - } - - @Nonnull - @Override - public WritableByteChannel openForAppend( @Nonnull final String path ) throws IOException - { - ByteArrayOutputStream stream = new ByteArrayOutputStream() - { - @Override - public void close() throws IOException - { - super.close(); - files.put( path, toByteArray() ); - } - }; - - byte[] current = files.get( path ); - if( current != null ) stream.write( current ); - - return Channels.newChannel( stream ); - } - - @Override - public long getRemainingSpace() - { - return 1000000L; - } - - @Override - public boolean exists( @Nonnull String path ) - { - return files.containsKey( path ) || directories.contains( path ); - } - - @Override - public boolean isDirectory( @Nonnull String path ) - { - return directories.contains( path ); - } - - @Override - public void list( @Nonnull String path, @Nonnull List files ) - { - for( String file : this.files.keySet() ) - { - if( file.startsWith( path ) ) files.add( file.substring( path.length() + 1 ) ); - } - } - - @Override - public long getSize( @Nonnull String path ) - { - throw new RuntimeException( "Not implemented" ); - } - - @Nonnull - @Override - public ReadableByteChannel openForRead( @Nonnull String path ) - { - return new ArrayByteChannel( files.get( path ) ); - } - - public MemoryMount addFile( String file, String contents ) - { - files.put( file, contents.getBytes() ); - return this; - } -} diff --git a/src/test/java/dan200/computercraft/core/filesystem/ResourceMountTest.java b/src/test/java/dan200/computercraft/core/filesystem/ResourceMountTest.java deleted file mode 100644 index 37f7e770f..000000000 --- a/src/test/java/dan200/computercraft/core/filesystem/ResourceMountTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.filesystem; - -import dan200.computercraft.api.filesystem.IMount; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -public class ResourceMountTest -{ - private IMount mount; - - @BeforeEach - public void before() - { -// ReloadableResourceManager manager = new SimpleResourceReloadListener(ResourceType.SERVER_DATA); -// manager.addResourcePack( new FolderPack( new File( "src/main/resources" ) ) ); -// -// mount = ResourceMount.get( "computercraft", "lua/rom", manager ); - } - - @Test - public void testList() throws IOException - { - List files = new ArrayList<>(); - mount.list( "", files ); - files.sort( Comparator.naturalOrder() ); - - assertEquals( - Arrays.asList( "apis", "autorun", "help", "modules", "motd.txt", "programs", "startup.lua" ), - files - ); - } - - @Test - public void testExists() throws IOException - { - assertTrue( mount.exists( "" ) ); - assertTrue( mount.exists( "startup.lua" ) ); - assertTrue( mount.exists( "programs/fun/advanced/paint.lua" ) ); - - assertFalse( mount.exists( "programs/fun/advance/paint.lua" ) ); - assertFalse( mount.exists( "programs/fun/advanced/paint.lu" ) ); - } - - @Test - public void testIsDir() throws IOException - { - assertTrue( mount.isDirectory( "" ) ); - } - - @Test - public void testIsFile() throws IOException - { - assertFalse( mount.isDirectory( "startup.lua" ) ); - } - - @Test - public void testSize() throws IOException - { - assertNotEquals( mount.getSize( "startup.lua" ), 0 ); - } -} diff --git a/src/test/java/dan200/computercraft/core/terminal/TextBufferTest.java b/src/test/java/dan200/computercraft/core/terminal/TextBufferTest.java deleted file mode 100644 index 286e62ad6..000000000 --- a/src/test/java/dan200/computercraft/core/terminal/TextBufferTest.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.terminal; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class TextBufferTest -{ - @Test - void testStringConstructor() - { - TextBuffer textBuffer = new TextBuffer( "test" ); - assertEquals( "test", textBuffer.toString() ); - } - - @Test - void testCharRepetitionConstructor() - { - TextBuffer textBuffer = new TextBuffer( 'a', 5 ); - assertEquals( "aaaaa", textBuffer.toString() ); - } - - @Test - void testLength() - { - TextBuffer textBuffer = new TextBuffer( "test" ); - assertEquals( 4, textBuffer.length() ); - } - - @Test - void testWrite() - { - TextBuffer textBuffer = new TextBuffer( ' ', 4 ); - textBuffer.write( "test" ); - assertEquals( "test", textBuffer.toString() ); - } - - @Test - void testWriteTextBuffer() - { - TextBuffer source = new TextBuffer( "test" ); - TextBuffer target = new TextBuffer( " " ); - target.write( source ); - assertEquals( "test", target.toString() ); - } - - @Test - void testWriteFromPos() - { - TextBuffer textBuffer = new TextBuffer( "test" ); - textBuffer.write( "il", 1 ); - assertEquals( "tilt", textBuffer.toString() ); - } - - @Test - void testWriteOutOfBounds() - { - TextBuffer textBuffer = new TextBuffer( "test" ); - textBuffer.write( "abcdefghijklmnop", -5 ); - assertEquals( "fghi", textBuffer.toString() ); - } - - @Test - void testWriteOutOfBounds2() - { - TextBuffer textBuffer = new TextBuffer( " " ); - textBuffer.write( "Hello, world!", -3 ); - assertEquals( "lo, world! ", textBuffer.toString() ); - } - - @Test - void testFill() - { - TextBuffer textBuffer = new TextBuffer( "test" ); - textBuffer.fill( 'c' ); - assertEquals( "cccc", textBuffer.toString() ); - } - - @Test - void testFillSubstring() - { - TextBuffer textBuffer = new TextBuffer( "test" ); - textBuffer.fill( 'c', 1, 3 ); - assertEquals( "tcct", textBuffer.toString() ); - } - - @Test - void testFillOutOfBounds() - { - TextBuffer textBuffer = new TextBuffer( "test" ); - textBuffer.fill( 'c', -5, 5 ); - assertEquals( "cccc", textBuffer.toString() ); - } - - @Test - void testCharAt() - { - TextBuffer textBuffer = new TextBuffer( "test" ); - assertEquals( 'e', textBuffer.charAt( 1 ) ); - } - - @Test - void testSetChar() - { - TextBuffer textBuffer = new TextBuffer( "test" ); - textBuffer.setChar( 2, 'n' ); - assertEquals( "tent", textBuffer.toString() ); - } - - @Test - void testSetCharWithNegativeIndex() - { - TextBuffer textBuffer = new TextBuffer( "test" ); - textBuffer.setChar( -5, 'n' ); - assertEquals( "test", textBuffer.toString(), "Buffer should not change after setting char with negative index." ); - } - - @Test - void testSetCharWithIndexBeyondBufferEnd() - { - TextBuffer textBuffer = new TextBuffer( "test" ); - textBuffer.setChar( 10, 'n' ); - assertEquals( "test", textBuffer.toString(), "Buffer should not change after setting char beyond buffer end." ); - } - - @Test - void testMultipleOperations() - { - TextBuffer textBuffer = new TextBuffer( ' ', 5 ); - textBuffer.setChar( 0, 'H' ); - textBuffer.setChar( 1, 'e' ); - textBuffer.setChar( 2, 'l' ); - textBuffer.write( "lo", 3 ); - assertEquals( "Hello", textBuffer.toString(), "TextBuffer failed to persist over multiple operations." ); - } - - @Test - void testEmptyBuffer() - { - TextBuffer textBuffer = new TextBuffer( "" ); - // exception on writing to empty buffer would fail the test - textBuffer.write( "test" ); - assertEquals( "", textBuffer.toString() ); - } -} diff --git a/src/test/java/dan200/computercraft/shared/wired/NetworkTest.java b/src/test/java/dan200/computercraft/shared/wired/NetworkTest.java deleted file mode 100644 index 2a69b9422..000000000 --- a/src/test/java/dan200/computercraft/shared/wired/NetworkTest.java +++ /dev/null @@ -1,463 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.wired; - -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.network.wired.IWiredElement; -import dan200.computercraft.api.network.wired.IWiredNetwork; -import dan200.computercraft.api.network.wired.IWiredNetworkChange; -import dan200.computercraft.api.network.wired.IWiredNode; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.shared.util.DirectionUtil; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Map; -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.BiFunction; - -import static org.junit.jupiter.api.Assertions.*; - -public class NetworkTest -{ - @Test - public void testConnect() - { - NetworkElement - aE = new NetworkElement( null, null, "a" ), - bE = new NetworkElement( null, null, "b" ), - cE = new NetworkElement( null, null, "c" ); - - IWiredNode - aN = aE.getNode(), - bN = bE.getNode(), - cN = cE.getNode(); - - assertNotEquals( aN.getNetwork(), bN.getNetwork(), "A's and B's network must be different" ); - assertNotEquals( aN.getNetwork(), cN.getNetwork(), "A's and C's network must be different" ); - assertNotEquals( bN.getNetwork(), cN.getNetwork(), "B's and C's network must be different" ); - - assertTrue( aN.getNetwork().connect( aN, bN ), "Must be able to add connection" ); - assertFalse( aN.getNetwork().connect( aN, bN ), "Cannot add connection twice" ); - - assertEquals( aN.getNetwork(), bN.getNetwork(), "A's and B's network must be equal" ); - assertEquals( Sets.newHashSet( aN, bN ), nodes( aN.getNetwork() ), "A's network should be A and B" ); - - assertEquals( Sets.newHashSet( "a", "b" ), aE.allPeripherals().keySet(), "A's peripheral set should be A, B" ); - assertEquals( Sets.newHashSet( "a", "b" ), bE.allPeripherals().keySet(), "B's peripheral set should be A, B" ); - - aN.getNetwork().connect( aN, cN ); - - assertEquals( aN.getNetwork(), bN.getNetwork(), "A's and B's network must be equal" ); - assertEquals( aN.getNetwork(), cN.getNetwork(), "A's and C's network must be equal" ); - assertEquals( Sets.newHashSet( aN, bN, cN ), nodes( aN.getNetwork() ), "A's network should be A, B and C" ); - - assertEquals( Sets.newHashSet( bN, cN ), neighbours( aN ), "A's neighbour set should be B, C" ); - assertEquals( Sets.newHashSet( aN ), neighbours( bN ), "B's neighbour set should be A" ); - assertEquals( Sets.newHashSet( aN ), neighbours( cN ), "C's neighbour set should be A" ); - - assertEquals( Sets.newHashSet( "a", "b", "c" ), aE.allPeripherals().keySet(), "A's peripheral set should be A, B, C" ); - assertEquals( Sets.newHashSet( "a", "b", "c" ), bE.allPeripherals().keySet(), "B's peripheral set should be A, B, C" ); - assertEquals( Sets.newHashSet( "a", "b", "c" ), cE.allPeripherals().keySet(), "C's peripheral set should be A, B, C" ); - } - - @Test - public void testDisconnectNoChange() - { - NetworkElement - aE = new NetworkElement( null, null, "a" ), - bE = new NetworkElement( null, null, "b" ), - cE = new NetworkElement( null, null, "c" ); - - IWiredNode - aN = aE.getNode(), - bN = bE.getNode(), - cN = cE.getNode(); - - aN.getNetwork().connect( aN, bN ); - aN.getNetwork().connect( aN, cN ); - aN.getNetwork().connect( bN, cN ); - - aN.getNetwork().disconnect( aN, bN ); - - assertEquals( aN.getNetwork(), bN.getNetwork(), "A's and B's network must be equal" ); - assertEquals( aN.getNetwork(), cN.getNetwork(), "A's and C's network must be equal" ); - assertEquals( Sets.newHashSet( aN, bN, cN ), nodes( aN.getNetwork() ), "A's network should be A, B and C" ); - - assertEquals( Sets.newHashSet( "a", "b", "c" ), aE.allPeripherals().keySet(), "A's peripheral set should be A, B, C" ); - assertEquals( Sets.newHashSet( "a", "b", "c" ), bE.allPeripherals().keySet(), "B's peripheral set should be A, B, C" ); - assertEquals( Sets.newHashSet( "a", "b", "c" ), cE.allPeripherals().keySet(), "C's peripheral set should be A, B, C" ); - } - - @Test - public void testDisconnectLeaf() - { - NetworkElement - aE = new NetworkElement( null, null, "a" ), - bE = new NetworkElement( null, null, "b" ), - cE = new NetworkElement( null, null, "c" ); - - IWiredNode - aN = aE.getNode(), - bN = bE.getNode(), - cN = cE.getNode(); - - aN.getNetwork().connect( aN, bN ); - aN.getNetwork().connect( aN, cN ); - - aN.getNetwork().disconnect( aN, bN ); - - assertNotEquals( aN.getNetwork(), bN.getNetwork(), "A's and B's network must not be equal" ); - assertEquals( aN.getNetwork(), cN.getNetwork(), "A's and C's network must be equal" ); - assertEquals( Sets.newHashSet( aN, cN ), nodes( aN.getNetwork() ), "A's network should be A and C" ); - assertEquals( Sets.newHashSet( bN ), nodes( bN.getNetwork() ), "B's network should be B" ); - - assertEquals( Sets.newHashSet( "a", "c" ), aE.allPeripherals().keySet(), "A's peripheral set should be A, C" ); - assertEquals( Sets.newHashSet( "b" ), bE.allPeripherals().keySet(), "B's peripheral set should be B" ); - assertEquals( Sets.newHashSet( "a", "c" ), cE.allPeripherals().keySet(), "C's peripheral set should be A, C" ); - } - - @Test - public void testDisconnectSplit() - { - NetworkElement - aE = new NetworkElement( null, null, "a" ), - aaE = new NetworkElement( null, null, "a_" ), - bE = new NetworkElement( null, null, "b" ), - bbE = new NetworkElement( null, null, "b_" ); - - IWiredNode - aN = aE.getNode(), - aaN = aaE.getNode(), - bN = bE.getNode(), - bbN = bbE.getNode(); - - aN.getNetwork().connect( aN, aaN ); - bN.getNetwork().connect( bN, bbN ); - - aN.getNetwork().connect( aN, bN ); - - aN.getNetwork().disconnect( aN, bN ); - - assertNotEquals( aN.getNetwork(), bN.getNetwork(), "A's and B's network must not be equal" ); - assertEquals( aN.getNetwork(), aaN.getNetwork(), "A's and A_'s network must be equal" ); - assertEquals( bN.getNetwork(), bbN.getNetwork(), "B's and B_'s network must be equal" ); - - assertEquals( Sets.newHashSet( aN, aaN ), nodes( aN.getNetwork() ), "A's network should be A and A_" ); - assertEquals( Sets.newHashSet( bN, bbN ), nodes( bN.getNetwork() ), "B's network should be B and B_" ); - - assertEquals( Sets.newHashSet( "a", "a_" ), aE.allPeripherals().keySet(), "A's peripheral set should be A and A_" ); - assertEquals( Sets.newHashSet( "b", "b_" ), bE.allPeripherals().keySet(), "B's peripheral set should be B and B_" ); - } - - @Test - public void testRemoveSingle() - { - NetworkElement aE = new NetworkElement( null, null, "a" ); - IWiredNode aN = aE.getNode(); - - IWiredNetwork network = aN.getNetwork(); - assertFalse( aN.remove(), "Cannot remove node from an empty network" ); - assertEquals( network, aN.getNetwork(), "Networks are same before and after" ); - } - - @Test - public void testRemoveLeaf() - { - NetworkElement - aE = new NetworkElement( null, null, "a" ), - bE = new NetworkElement( null, null, "b" ), - cE = new NetworkElement( null, null, "c" ); - - IWiredNode - aN = aE.getNode(), - bN = bE.getNode(), - cN = cE.getNode(); - - aN.getNetwork().connect( aN, bN ); - aN.getNetwork().connect( aN, cN ); - - assertTrue( aN.getNetwork().remove( bN ), "Must be able to remove node" ); - assertFalse( aN.getNetwork().remove( bN ), "Cannot remove a second time" ); - - assertNotEquals( aN.getNetwork(), bN.getNetwork(), "A's and B's network must not be equal" ); - assertEquals( aN.getNetwork(), cN.getNetwork(), "A's and C's network must be equal" ); - - assertEquals( Sets.newHashSet( aN, cN ), nodes( aN.getNetwork() ), "A's network should be A and C" ); - assertEquals( Sets.newHashSet( bN ), nodes( bN.getNetwork() ), "B's network should be B" ); - - assertEquals( Sets.newHashSet( "a", "c" ), aE.allPeripherals().keySet(), "A's peripheral set should be A, C" ); - assertEquals( Sets.newHashSet(), bE.allPeripherals().keySet(), "B's peripheral set should be empty" ); - assertEquals( Sets.newHashSet( "a", "c" ), cE.allPeripherals().keySet(), "C's peripheral set should be A, C" ); - } - - @Test - public void testRemoveSplit() - { - NetworkElement - aE = new NetworkElement( null, null, "a" ), - aaE = new NetworkElement( null, null, "a_" ), - bE = new NetworkElement( null, null, "b" ), - bbE = new NetworkElement( null, null, "b_" ), - cE = new NetworkElement( null, null, "c" ); - - IWiredNode - aN = aE.getNode(), - aaN = aaE.getNode(), - bN = bE.getNode(), - bbN = bbE.getNode(), - cN = cE.getNode(); - - aN.getNetwork().connect( aN, aaN ); - bN.getNetwork().connect( bN, bbN ); - - cN.getNetwork().connect( aN, cN ); - cN.getNetwork().connect( bN, cN ); - - cN.getNetwork().remove( cN ); - - assertNotEquals( aN.getNetwork(), bN.getNetwork(), "A's and B's network must not be equal" ); - assertEquals( aN.getNetwork(), aaN.getNetwork(), "A's and A_'s network must be equal" ); - assertEquals( bN.getNetwork(), bbN.getNetwork(), "B's and B_'s network must be equal" ); - - assertEquals( Sets.newHashSet( aN, aaN ), nodes( aN.getNetwork() ), "A's network should be A and A_" ); - assertEquals( Sets.newHashSet( bN, bbN ), nodes( bN.getNetwork() ), "B's network should be B and B_" ); - assertEquals( Sets.newHashSet( cN ), nodes( cN.getNetwork() ), "C's network should be C" ); - - assertEquals( Sets.newHashSet( "a", "a_" ), aE.allPeripherals().keySet(), "A's peripheral set should be A and A_" ); - assertEquals( Sets.newHashSet( "b", "b_" ), bE.allPeripherals().keySet(), "B's peripheral set should be B and B_" ); - assertEquals( Sets.newHashSet(), cE.allPeripherals().keySet(), "C's peripheral set should be empty" ); - } - - private static final int BRUTE_SIZE = 16; - private static final int TOGGLE_CONNECTION_TIMES = 5; - private static final int TOGGLE_NODE_TIMES = 5; - - @Test - @Disabled( "Takes a long time to run, mostly for stress testing" ) - public void testLarge() - { - Grid grid = new Grid<>( BRUTE_SIZE ); - grid.map( ( existing, pos ) -> new NetworkElement( null, null, "n_" + pos ).getNode() ); - - // Test connecting - { - long start = System.nanoTime(); - - grid.forEach( ( existing, pos ) -> { - for( Direction facing : DirectionUtil.FACINGS ) - { - BlockPos offset = pos.offset( facing ); - if( offset.getX() > BRUTE_SIZE / 2 == pos.getX() > BRUTE_SIZE / 2 ) - { - IWiredNode other = grid.get( offset ); - if( other != null ) existing.getNetwork().connect( existing, other ); - } - } - } ); - - long end = System.nanoTime(); - - System.out.printf( "Connecting %s³ nodes took %s seconds\n", BRUTE_SIZE, (end - start) * 1e-9 ); - } - - // Test toggling - { - IWiredNode left = grid.get( new BlockPos( BRUTE_SIZE / 2, 0, 0 ) ); - IWiredNode right = grid.get( new BlockPos( BRUTE_SIZE / 2 + 1, 0, 0 ) ); - assertNotEquals( left.getNetwork(), right.getNetwork() ); - - long start = System.nanoTime(); - for( int i = 0; i < TOGGLE_CONNECTION_TIMES; i++ ) - { - left.getNetwork().connect( left, right ); - left.getNetwork().disconnect( left, right ); - } - - long end = System.nanoTime(); - - System.out.printf( "Toggling connection %s times took %s seconds\n", TOGGLE_CONNECTION_TIMES, (end - start) * 1e-9 ); - } - - { - IWiredNode left = grid.get( new BlockPos( BRUTE_SIZE / 2, 0, 0 ) ); - IWiredNode right = grid.get( new BlockPos( BRUTE_SIZE / 2 + 1, 0, 0 ) ); - IWiredNode centre = new NetworkElement( null, null, "c" ).getNode(); - assertNotEquals( left.getNetwork(), right.getNetwork() ); - - long start = System.nanoTime(); - for( int i = 0; i < TOGGLE_NODE_TIMES; i++ ) - { - left.getNetwork().connect( left, centre ); - right.getNetwork().connect( right, centre ); - - left.getNetwork().remove( centre ); - } - - long end = System.nanoTime(); - - System.out.printf( "Toggling node %s times took %s seconds\n", TOGGLE_NODE_TIMES, (end - start) * 1e-9 ); - } - } - - private static final class NetworkElement implements IWiredElement - { - private final World world; - private final Vec3d position; - private final String id; - private final IWiredNode node; - private final Map localPeripherals = Maps.newHashMap(); - private final Map remotePeripherals = Maps.newHashMap(); - - private NetworkElement( World world, Vec3d position, String id ) - { - this.world = world; - this.position = position; - this.id = id; - this.node = ComputerCraftAPI.createWiredNodeForElement( this ); - this.addPeripheral( id ); - } - - @Nonnull - @Override - public World getWorld() - { - return world; - } - - @Nonnull - @Override - public Vec3d getPosition() - { - return position; - } - - @Nonnull - @Override - public String getSenderID() - { - return id; - } - - @Override - public String toString() - { - return "NetworkElement{" + id + "}"; - } - - @Nonnull - @Override - public IWiredNode getNode() - { - return node; - } - - @Override - public void networkChanged( @Nonnull IWiredNetworkChange change ) - { - remotePeripherals.keySet().removeAll( change.peripheralsRemoved().keySet() ); - remotePeripherals.putAll( change.peripheralsAdded() ); - } - - public NetworkElement addPeripheral( String name ) - { - localPeripherals.put( name, new NetworkPeripheral() ); - getNode().updatePeripherals( localPeripherals ); - return this; - } - - @Nonnull - public Map allPeripherals() - { - return remotePeripherals; - } - } - - private static class NetworkPeripheral implements IPeripheral - { - @Nonnull - @Override - public String getType() - { - return "test"; - } - - @Override - public boolean equals( @Nullable IPeripheral other ) - { - return this == other; - } - } - - private static class Grid - { - private final int size; - private final T[] box; - - @SuppressWarnings( "unchecked" ) - Grid( int size ) - { - this.size = size; - this.box = (T[]) new Object[size * size * size]; - } - - public T get( BlockPos pos ) - { - int x = pos.getX(), y = pos.getY(), z = pos.getZ(); - - return x >= 0 && x < size && y >= 0 && y < size && z >= 0 && z < size - ? box[x * size * size + y * size + z] - : null; - } - - public void forEach( BiConsumer transform ) - { - for( int x = 0; x < size; x++ ) - { - for( int y = 0; y < size; y++ ) - { - for( int z = 0; z < size; z++ ) - { - transform.accept( box[x * size * size + y * size + z], new BlockPos( x, y, z ) ); - } - } - } - } - - public void map( BiFunction transform ) - { - for( int x = 0; x < size; x++ ) - { - for( int y = 0; y < size; y++ ) - { - for( int z = 0; z < size; z++ ) - { - box[x * size * size + y * size + z] = transform.apply( box[x * size * size + y * size + z], new BlockPos( x, y, z ) ); - } - } - } - } - } - - private static Set nodes( IWiredNetwork network ) - { - return ((WiredNetwork) network).nodes; - } - - private static Set neighbours( IWiredNode node ) - { - return ((WiredNode) node).neighbours; - } -} diff --git a/src/test/resources/tags.html b/src/test/resources/tags.html deleted file mode 100644 index 84d2a7c37..000000000 --- a/src/test/resources/tags.html +++ /dev/null @@ -1,1823 +0,0 @@ -c:advanced_alloy_ingots -techreborn:advanced_alloy_ingot -c:advanced_alloy_plates -techreborn:advanced_alloy_plate -c:alexandrite -more_gems:alexandrite -c:almandine_dusts -techreborn:almandine_dust -c:almandine_small_dusts -techreborn:almandine_small_dust -2 -c:aluminum_blocks -c:aluminum_block -techreborn:aluminum_storage_block -2 -c:aluminum_dusts -c:aluminum_dust -techreborn:aluminum_dust -c:aluminum_gears -c:aluminum_gear -2 -c:aluminum_ingots -c:aluminum_ingot -techreborn:aluminum_ingot -2 -c:aluminum_nuggets -c:aluminum_nugget -techreborn:aluminum_nugget -3 -c:aluminum_ores -c:aluminum_ore -c:aluminum_nether_ore -c:aluminum_end_ore -2 -c:aluminum_plates -c:aluminum_plate -techreborn:aluminum_plate -c:aluminum_small_dusts -techreborn:aluminum_small_dust -c:amethyst -more_gems:amethyst -c:amethyst_blocks -c:amethyst_block -c:amethyst_dusts -c:amethyst_dust -c:amethyst_gears -c:amethyst_gear -3 -c:amethyst_ores -c:amethyst_ore -c:amethyst_nether_ore -c:amethyst_end_ore -c:amethyst_plates -c:amethyst_plate -c:amethysts -c:amethyst -c:ancient_debris -minecraft:ancient_debris -c:andesite_dusts -techreborn:andesite_dust -c:andesite_small_dusts -techreborn:andesite_small_dust -c:andradite_dusts -techreborn:andradite_dust -c:andradite_small_dusts -techreborn:andradite_small_dust -c:ashes_dusts -techreborn:ashes_dust -c:ashes_small_dusts -techreborn:ashes_small_dust -c:asterite_blocks -astromine:asterite_block -c:asterite_dusts -astromine:asterite_dust -c:asterite_fragments -astromine:asterite_fragment -c:asterite_nuggets -#c:asterite_fragments -c:asterite_ores -#c:asteroid_asterite_ores -c:asterite_tiny_dusts -astromine:asterite_tiny_dust -c:asterites -astromine:asterite -c:asteroid_asterite_clusters -astromine:asteroid_asterite_cluster -c:asteroid_asterite_ores -astromine:asteroid_asterite_ore -c:asteroid_coal_clusters -astromine:asteroid_coal_cluster -c:asteroid_coal_ores -astromine:asteroid_coal_ore -c:asteroid_copper_clusters -astromine:asteroid_copper_cluster -c:asteroid_copper_ores -astromine:asteroid_copper_ore -c:asteroid_diamond_clusters -astromine:asteroid_diamond_cluster -c:asteroid_diamond_ores -astromine:asteroid_diamond_ore -c:asteroid_emerald_clusters -astromine:asteroid_emerald_cluster -c:asteroid_emerald_ores -astromine:asteroid_emerald_ore -c:asteroid_galaxium_clusters -astromine:asteroid_galaxium_cluster -c:asteroid_galaxium_ores -astromine:asteroid_galaxium_ore -c:asteroid_gold_clusters -astromine:asteroid_gold_cluster -c:asteroid_gold_ores -astromine:asteroid_gold_ore -c:asteroid_iron_clusters -astromine:asteroid_iron_cluster -c:asteroid_iron_ores -astromine:asteroid_iron_ore -c:asteroid_lapis_clusters -astromine:asteroid_lapis_cluster -c:asteroid_lapis_ores -astromine:asteroid_lapis_ore -c:asteroid_lead_clusters -astromine:asteroid_lead_cluster -c:asteroid_lead_ores -astromine:asteroid_lead_ore -c:asteroid_metite_clusters -astromine:asteroid_metite_cluster -c:asteroid_metite_ores -astromine:asteroid_metite_ore -c:asteroid_redstone_clusters -astromine:asteroid_redstone_cluster -c:asteroid_redstone_ores -astromine:asteroid_redstone_ore -c:asteroid_silver_clusters -astromine:asteroid_silver_cluster -c:asteroid_silver_ores -astromine:asteroid_silver_ore -c:asteroid_stellum_clusters -astromine:asteroid_stellum_cluster -c:asteroid_stellum_ores -astromine:asteroid_stellum_ore -c:asteroid_tin_clusters -astromine:asteroid_tin_cluster -c:asteroid_tin_ores -astromine:asteroid_tin_ore -2 -c:basalt -minecraft:basalt -minecraft:polished_basalt -c:basalt_dusts -techreborn:basalt_dust -c:basalt_small_dusts -techreborn:basalt_small_dust -c:bauxite_dusts -techreborn:bauxite_dust -c:bauxite_ores -techreborn:bauxite_ore -c:bauxite_small_dusts -techreborn:bauxite_small_dust -c:black_dyes -minecraft:black_dye -c:blue_dyes -minecraft:blue_dye -15 -c:boots -astromine:tin_boots -astromine:copper_boots -astromine:silver_boots -astromine:lead_boots -astromine:steel_boots -astromine:bronze_boots -astromine:electrum_boots -astromine:rose_gold_boots -astromine:sterling_silver_boots -astromine:fools_gold_boots -astromine:metite_boots -astromine:asterite_boots -astromine:stellum_boots -astromine:galaxium_boots -astromine:univite_boots -2 -c:brass_blocks -c:brass_block -techreborn:brass_storage_block -2 -c:brass_dusts -c:brass_dust -techreborn:brass_dust -c:brass_gears -c:brass_gear -3 -c:brass_ingots -c:brass_ingot -mechanized:brass_ingot -techreborn:brass_ingot -2 -c:brass_nuggets -c:brass_nugget -techreborn:brass_nugget -2 -c:brass_plates -c:brass_plate -techreborn:brass_plate -c:brass_small_dusts -techreborn:brass_small_dust -3 -c:bronze_blocks -astromine:bronze_block -c:bronze_block -techreborn:bronze_storage_block -3 -c:bronze_dusts -astromine:bronze_dust -c:bronze_dust -techreborn:bronze_dust -2 -c:bronze_gears -astromine:bronze_gear -c:bronze_gear -3 -c:bronze_ingots -astromine:bronze_ingot -c:bronze_ingot -techreborn:bronze_ingot -3 -c:bronze_nuggets -astromine:bronze_nugget -c:bronze_nugget -techreborn:bronze_nugget -3 -c:bronze_plates -astromine:bronze_plates -c:bronze_plate -techreborn:bronze_plate -c:bronze_small_dusts -techreborn:bronze_small_dust -c:bronze_tiny_dusts -astromine:bronze_tiny_dust -c:brown_dyes -minecraft:brown_dye -c:calcite_dusts -techreborn:calcite_dust -c:calcite_small_dusts -techreborn:calcite_small_dust -c:carbon_plates -techreborn:carbon_plate -c:carbonado -more_gems:carbonado -c:carbs -minecraft:potato -2 -c:certus_quartz_crystals -appliedenergistics2:certus_quartz_crystal -appliedenergistics2:charged_certus_quartz_crystal -2 -c:certus_quartz_ores -appliedenergistics2:quartz_ore -appliedenergistics2:charged_quartz_ore -c:charcoal -minecraft:charcoal -2 -c:charcoal_dusts -astromine:charcoal_dust -techreborn:charcoal_dust -c:charcoal_small_dusts -techreborn:charcoal_small_dust -c:charcoal_tiny_dusts -astromine:charcoal_tiny_dust -3 -c:chest -minecraft:chest -minecraft:trapped_chest -expandedstorage:wood_chest -15 -c:chestplates -astromine:tin_chestplate -astromine:copper_chestplate -astromine:silver_chestplate -astromine:lead_chestplate -astromine:steel_chestplate -astromine:bronze_chestplate -astromine:electrum_chestplate -astromine:rose_gold_chestplate -astromine:sterling_silver_chestplate -astromine:fools_gold_chestplate -astromine:metite_chestplate -astromine:asterite_chestplate -astromine:stellum_chestplate -astromine:galaxium_chestplate -astromine:univite_chestplate -c:chrome_blocks -techreborn:chrome_storage_block -c:chrome_dusts -techreborn:chrome_dust -c:chrome_ingots -techreborn:chrome_ingot -c:chrome_nuggets -techreborn:chrome_nugget -c:chrome_plates -techreborn:chrome_plate -c:chrome_small_dusts -techreborn:chrome_small_dust -c:cinnabar_dusts -techreborn:cinnabar_dust -c:cinnabar_ores -techreborn:cinnabar_ore -c:cinnabar_small_dusts -techreborn:cinnabar_small_dust -c:citrine -more_gems:citrine -c:clay_dusts -techreborn:clay_dust -c:clay_small_dusts -techreborn:clay_small_dust -c:coal -minecraft:coal -c:coal_blocks -minecraft:coal_block -c:coal_coke_blocks -c:coal_coke_block -c:coal_cokes -c:coal_coke -3 -c:coal_dusts -astromine:coal_dust -indrev:coal_dust -techreborn:coal_dust -2 -c:coal_ores -minecraft:coal_ore -#c:asteroid_coal_ores -c:coal_plates -techreborn:coal_plate -c:coal_small_dusts -techreborn:coal_small_dust -c:coal_tiny_dusts -astromine:coal_tiny_dust -c:cobalt_blocks -c:cobalt_block -c:cobalt_dusts -c:cobalt_dust -c:cobalt_gears -c:cobalt_gear -c:cobalt_ingots -c:cobalt_ingot -c:cobalt_nuggets -c:cobalt_nugget -3 -c:cobalt_ores -c:cobalt_ore -c:cobalt_nether_ore -c:cobalt_end_ore -c:cobalt_plates -c:cobalt_plate -c:cobblestones -minecraft:cobblestone -16 -c:concrete -minecraft:white_concrete -minecraft:orange_concrete -minecraft:magenta_concrete -minecraft:light_blue_concrete -minecraft:yellow_concrete -minecraft:lime_concrete -minecraft:pink_concrete -minecraft:gray_concrete -minecraft:light_gray_concrete -minecraft:cyan_concrete -minecraft:purple_concrete -minecraft:blue_concrete -minecraft:brown_concrete -minecraft:green_concrete -minecraft:red_concrete -minecraft:black_concrete -16 -c:concrete_powder -minecraft:white_concrete_powder -minecraft:orange_concrete_powder -minecraft:magenta_concrete_powder -minecraft:light_blue_concrete_powder -minecraft:yellow_concrete_powder -minecraft:lime_concrete_powder -minecraft:pink_concrete_powder -minecraft:gray_concrete_powder -minecraft:light_gray_concrete_powder -minecraft:cyan_concrete_powder -minecraft:purple_concrete_powder -minecraft:blue_concrete_powder -minecraft:brown_concrete_powder -minecraft:green_concrete_powder -minecraft:red_concrete_powder -minecraft:black_concrete_powder -c:cooked_meat -epicurean:tofu -3 -c:copper_blocks -astromine:copper_block -c:copper_block -techreborn:copper_storage_block -4 -c:copper_dusts -astromine:copper_dust -c:copper_dust -indrev:copper_dust -techreborn:copper_dust -2 -c:copper_gears -astromine:copper_gear -c:copper_gear -c:copper_ingot -mechanized:copper_ingot -6 -c:copper_ingots -astromine:copper_ingot -c:copper_ingot -ironchest,indrev:copper_ingot -#c:copper_ingot -mechanized:copper_ingot -techreborn:copper_ingot -3 -c:copper_nuggets -astromine:copper_nugget -c:copper_nugget -techreborn:copper_nugget -c:copper_ore -mechanized:copper_ore -8 -c:copper_ores -astromine:copper_ore -#c:asteroid_copper_ores -c:copper_ore -c:copper_nether_ore -c:copper_end_ore -indrev:copper_ore -mechanized:copper_ore -techreborn:copper_ore -4 -c:copper_plates -astromine:copper_plates -c:copper_plate -indrev:copper_plate -techreborn:copper_plate -c:copper_small_dusts -techreborn:copper_small_dust -c:copper_tiny_dusts -astromine:copper_tiny_dust -c:copper_wires -astromine:copper_wire -c:corn -veggie_way:corn -c:corundum -more_gems:corundum -c:cyan_dyes -minecraft:cyan_dye -2 -c:dark_ashes_dusts -cinderscapes:ash_pile -techreborn:dark_ashes_dust -c:dark_ashes_small_dusts -techreborn:dark_ashes_small_dust -c:diamond_blocks -minecraft:diamond_block -4 -c:diamond_dusts -astromine:diamond_dust -c:diamond_dust -indrev:diamond_dust -techreborn:diamond_dust -c:diamond_fragments -astromine:diamond_fragment -c:diamond_gears -c:diamond_gear -2 -c:diamond_nuggets -#c:diamond_fragments -techreborn:diamond_nugget -2 -c:diamond_ores -minecraft:diamond_ore -#c:asteroid_diamond_ores -2 -c:diamond_plates -c:diamond_plate -techreborn:diamond_plate -c:diamond_small_dusts -techreborn:diamond_small_dust -c:diamond_tiny_dusts -astromine:diamond_tiny_dust -c:diamonds -minecraft:diamond -c:diorite_dusts -techreborn:diorite_dust -c:diorite_small_dusts -techreborn:diorite_small_dust -16 -c:dye_any -#c:dye_black -#c:dye_blue -#c:dye_brown -#c:dye_cyan -#c:dye_gray -#c:dye_green -#c:dye_light_blue -#c:dye_light_gray -#c:dye_lime -#c:dye_magenta -#c:dye_orange -#c:dye_pink -#c:dye_purple -#c:dye_red -#c:dye_white -#c:dye_yellow -c:dye_black -minecraft:black_dye -c:dye_blue -minecraft:blue_dye -c:dye_brown -minecraft:brown_dye -c:dye_cyan -minecraft:cyan_dye -c:dye_gray -minecraft:gray_dye -c:dye_green -minecraft:green_dye -c:dye_light_blue -minecraft:light_blue_dye -c:dye_light_gray -minecraft:light_gray_dye -c:dye_lime -minecraft:lime_dye -c:dye_magenta -minecraft:magenta_dye -c:dye_orange -minecraft:orange_dye -c:dye_pink -minecraft:pink_dye -c:dye_purple -minecraft:purple_dye -c:dye_red -minecraft:red_dye -c:dye_white -minecraft:white_dye -c:dye_yellow -minecraft:yellow_dye -3 -c:electrum_blocks -astromine:electrum_block -c:electrum_block -techreborn:electrum_storage_block -3 -c:electrum_dusts -astromine:electrum_dust -c:electrum_dust -techreborn:electrum_dust -2 -c:electrum_gears -astromine:electrum_gear -c:electrum_gear -3 -c:electrum_ingots -astromine:electrum_ingot -c:electrum_ingot -techreborn:electrum_ingot -3 -c:electrum_nuggets -astromine:electrum_nugget -c:electrum_nugget -techreborn:electrum_nugget -3 -c:electrum_plates -astromine:electrum_plates -c:electrum_plate -techreborn:electrum_plate -c:electrum_small_dusts -techreborn:electrum_small_dust -c:electrum_tiny_dusts -astromine:electrum_tiny_dust -c:electrum_wires -astromine:electrum_wire -c:emerald_blocks -minecraft:emerald_block -3 -c:emerald_dusts -astromine:emerald_dust -c:emerald_dust -techreborn:emerald_dust -c:emerald_fragments -astromine:emerald_fragment -c:emerald_gears -c:emerald_gear -2 -c:emerald_nuggets -#c:emerald_fragments -techreborn:emerald_nugget -2 -c:emerald_ores -minecraft:emerald_ore -#c:asteroid_emerald_ores -2 -c:emerald_plates -c:emerald_plate -techreborn:emerald_plate -c:emerald_small_dusts -techreborn:emerald_small_dust -c:emerald_tiny_dusts -astromine:emerald_tiny_dust -c:emeralds -minecraft:emerald -c:ender_eye_dusts -techreborn:ender_eye_dust -c:ender_eye_small_dusts -techreborn:ender_eye_small_dust -2 -c:ender_pearl_dusts -appliedenergistics2:ender_dust -techreborn:ender_pearl_dust -c:ender_pearl_small_dusts -techreborn:ender_pearl_small_dust -c:ender_pearls -minecraft:ender_pearl -c:endstone_dusts -techreborn:endstone_dust -c:endstone_small_dusts -techreborn:endstone_small_dust -c:flint_dusts -techreborn:flint_dust -c:flint_small_dusts -techreborn:flint_small_dust -c:flour -veggie_way:flour -c:fools_gold_blocks -astromine:fools_gold_block -c:fools_gold_dusts -astromine:fools_gold_dust -c:fools_gold_gears -astromine:fools_gold_gear -c:fools_gold_ingots -astromine:fools_gold_ingot -c:fools_gold_nuggets -astromine:fools_gold_nugget -c:fools_gold_plates -astromine:fools_gold_plates -c:fools_gold_tiny_dusts -astromine:fools_gold_tiny_dust -7 -c:fruits -minecraft:beetroot -minecraft:apple -minecraft:melon_slice -minecraft:sweet_berries -minecraft:honeycomb -minecraft:sugar_cane -veggie_way:cactus_chunk -c:galaxium_blocks -astromine:galaxium_block -c:galaxium_dusts -astromine:galaxium_dust -c:galaxium_fragments -astromine:galaxium_fragment -c:galaxium_nuggets -#c:galaxium_fragments -c:galaxium_ores -#c:asteroid_galaxium_ores -c:galaxium_tiny_dusts -astromine:galaxium_tiny_dust -c:galaxiums -astromine:galaxium -c:galena_dusts -techreborn:galena_dust -c:galena_ores -techreborn:galena_ore -c:galena_small_dusts -techreborn:galena_small_dust -11 -c:gems -more_gems:citrine -more_gems:tourmaline -more_gems:topaz -more_gems:alexandrite -more_gems:corundum -more_gems:sapphire -more_gems:carbonado -more_gems:amethyst -more_gems:ruby -minecraft:diamond -minecraft:emerald -17 -c:glass -minecraft:glass -minecraft:white_stained_glass -minecraft:orange_stained_glass -minecraft:magenta_stained_glass -minecraft:light_blue_stained_glass -minecraft:yellow_stained_glass -minecraft:lime_stained_glass -minecraft:pink_stained_glass -minecraft:gray_stained_glass -minecraft:light_gray_stained_glass -minecraft:cyan_stained_glass -minecraft:purple_stained_glass -minecraft:blue_stained_glass -minecraft:brown_stained_glass -minecraft:green_stained_glass -minecraft:red_stained_glass -minecraft:black_stained_glass -33 -c:glass_blocks -minecraft:glass -minecraft:white_stained_glass -appliedenergistics2,minecraft:orange_stained_glass -appliedenergistics2,minecraft:magenta_stained_glass -appliedenergistics2,minecraft:light_blue_stained_glass -appliedenergistics2,minecraft:yellow_stained_glass -appliedenergistics2,minecraft:lime_stained_glass -appliedenergistics2,minecraft:pink_stained_glass -appliedenergistics2,minecraft:gray_stained_glass -appliedenergistics2,minecraft:light_gray_stained_glass -appliedenergistics2,minecraft:cyan_stained_glass -appliedenergistics2,minecraft:purple_stained_glass -appliedenergistics2,minecraft:blue_stained_glass -appliedenergistics2,minecraft:brown_stained_glass -appliedenergistics2,minecraft:green_stained_glass -appliedenergistics2,minecraft:red_stained_glass -appliedenergistics2,minecraft:black_stained_glass -appliedenergistics2,xb:g -xb:gk -xb:gb -xb:gw -xb:gc -xb:gn -xb:gg -xb:gu -xb:ga -xb:gl -xb:gm -xb:go -xb:gp -xb:gv -xb:gr -xb:gy -17 -c:glass_panes -minecraft:glass_pane -minecraft:black_stained_glass_pane -minecraft:white_stained_glass_pane -minecraft:gray_stained_glass_pane -minecraft:light_gray_stained_glass_pane -minecraft:blue_stained_glass_pane -minecraft:light_blue_stained_glass_pane -minecraft:cyan_stained_glass_pane -minecraft:lime_stained_glass_pane -minecraft:green_stained_glass_pane -minecraft:orange_stained_glass_pane -minecraft:yellow_stained_glass_pane -minecraft:red_stained_glass_pane -minecraft:magenta_stained_glass_pane -minecraft:brown_stained_glass_pane -minecraft:purple_stained_glass_pane -minecraft:pink_stained_glass_pane -c:glowstone_dusts -minecraft:glowstone_dust -c:glowstone_small_dusts -techreborn:glowstone_small_dust -c:gold_blocks -minecraft:gold_block -5 -c:gold_dusts -appliedenergistics2:gold_dust -astromine:gold_dust -c:gold_dust -indrev:gold_dust -techreborn:gold_dust -2 -c:gold_gears -astromine:gold_gear -c:gold_gear -c:gold_ingots -minecraft:gold_ingot -c:gold_nuggets -minecraft:gold_nugget -3 -c:gold_ores -minecraft:gold_ore -#c:asteroid_gold_ores -minecraft:nether_gold_ore -4 -c:gold_plates -astromine:gold_plates -c:gold_plate -indrev:gold_plate -techreborn:gold_plate -c:gold_small_dusts -techreborn:gold_small_dust -c:gold_tiny_dusts -astromine:gold_tiny_dust -c:gold_wires -astromine:gold_wire -c:grain -minecraft:wheat -c:granite_dusts -techreborn:granite_dust -c:granite_small_dusts -techreborn:granite_small_dust -c:gray_dyes -minecraft:gray_dye -c:green_dyes -minecraft:green_dye -c:grossular_dusts -techreborn:grossular_dust -c:grossular_small_dusts -techreborn:grossular_small_dust -15 -c:helmets -astromine:tin_helmet -astromine:copper_helmet -astromine:silver_helmet -astromine:lead_helmet -astromine:steel_helmet -astromine:bronze_helmet -astromine:electrum_helmet -astromine:rose_gold_helmet -astromine:sterling_silver_helmet -astromine:fools_gold_helmet -astromine:metite_helmet -astromine:asterite_helmet -astromine:stellum_helmet -astromine:galaxium_helmet -astromine:univite_helmet -c:hot_tungstensteel_ingots -techreborn:hot_tungstensteel_ingot -c:hot_tungstensteel_nuggets -techreborn:hot_tungstensteel_nugget -c:invar_blocks -techreborn:invar_storage_block -c:invar_dusts -techreborn:invar_dust -c:invar_ingots -techreborn:invar_ingot -c:invar_nuggets -techreborn:invar_nugget -c:invar_plates -techreborn:invar_plate -c:invar_small_dusts -techreborn:invar_small_dust -c:iridium_alloy_ingots -techreborn:iridium_alloy_ingot -c:iridium_alloy_plates -techreborn:iridium_alloy_plate -2 -c:iridium_blocks -c:iridium_block -techreborn:iridium_storage_block -c:iridium_dusts -c:iridium_dust -c:iridium_gears -c:iridium_gear -2 -c:iridium_ingots -c:iridium_ingot -techreborn:iridium_ingot -2 -c:iridium_nuggets -c:iridium_nugget -techreborn:iridium_nugget -4 -c:iridium_ores -c:iridium_ore -c:iridium_nether_ore -c:iridium_end_ore -techreborn:iridium_ore -2 -c:iridium_plates -c:iridium_plate -techreborn:iridium_plate -c:iridium_reinforced_stone_blocks -techreborn:iridium_reinforced_stone_storage_block -c:iridium_reinforced_tungstensteel_blocks -techreborn:iridium_reinforced_tungstensteel_storage_block -c:iron_blocks -minecraft:iron_block -5 -c:iron_dusts -appliedenergistics2:iron_dust -astromine:iron_dust -c:iron_dust -indrev:iron_dust -techreborn:iron_dust -2 -c:iron_gears -astromine:iron_gear -c:iron_gear -c:iron_ingots -minecraft:iron_ingot -c:iron_nuggets -minecraft:iron_nugget -2 -c:iron_ores -minecraft:iron_ore -#c:asteroid_iron_ores -4 -c:iron_plates -astromine:iron_plates -c:iron_plate -indrev:iron_plate -techreborn:iron_plate -c:iron_small_dusts -techreborn:iron_small_dust -c:iron_tiny_dusts -astromine:iron_tiny_dust -c:lapis_blocks -minecraft:lapis_block -c:lapis_dusts -astromine:lapis_dust -c:lapis_lazulis -minecraft:lapis_lazuli -2 -c:lapis_ores -minecraft:lapis_ore -#c:asteroid_lapis_ores -c:lapis_plates -techreborn:lapis_plate -c:lapis_tiny_dusts -astromine:lapis_tiny_dust -c:lazurite_dusts -techreborn:lazurite_dust -c:lazurite_plates -techreborn:lazurite_plate -c:lazurite_small_dusts -techreborn:lazurite_small_dust -3 -c:lead_blocks -astromine:lead_block -c:lead_block -techreborn:lead_storage_block -3 -c:lead_dusts -astromine:lead_dust -c:lead_dust -techreborn:lead_dust -2 -c:lead_gears -astromine:lead_gear -c:lead_gear -3 -c:lead_ingots -astromine:lead_ingot -c:lead_ingot -techreborn:lead_ingot -3 -c:lead_nuggets -astromine:lead_nugget -c:lead_nugget -techreborn:lead_nugget -6 -c:lead_ores -astromine:lead_ore -#c:asteroid_lead_ores -c:lead_ore -c:lead_nether_ore -c:lead_end_ore -techreborn:lead_ore -3 -c:lead_plates -astromine:lead_plates -c:lead_plate -techreborn:lead_plate -c:lead_small_dusts -techreborn:lead_small_dust -c:lead_tiny_dusts -astromine:lead_tiny_dust -c:lead_wires -astromine:lead_wire -c:leather -minecraft:leather -15 -c:leggings -astromine:tin_leggings -astromine:copper_leggings -astromine:silver_leggings -astromine:lead_leggings -astromine:steel_leggings -astromine:bronze_leggings -astromine:electrum_leggings -astromine:rose_gold_leggings -astromine:sterling_silver_leggings -astromine:fools_gold_leggings -astromine:metite_leggings -astromine:asterite_leggings -astromine:stellum_leggings -astromine:galaxium_leggings -astromine:univite_leggings -c:lentil -veggie_way:lentil -c:light_blue_dyes -minecraft:light_blue_dye -c:light_gray_dyes -minecraft:light_gray_dye -c:lime_dyes -minecraft:lime_dye -5 -c:limestone -blockus:limestone -blockus:limestone_bricks -blockus:limestone_pillar -blockus:chiseled_limestone -blockus:limestone_circle_pavement -c:magenta_dyes -minecraft:magenta_dye -c:magnalium_plates -techreborn:magnalium_plate -c:magnesium_dusts -techreborn:magnesium_dust -c:magnesium_small_dusts -techreborn:magnesium_small_dust -c:manganese_dusts -techreborn:manganese_dust -c:manganese_small_dusts -techreborn:manganese_small_dust -6 -c:marble -blockus:marble -blockus:marble_bricks -blockus:marble_pillar -blockus:chiseled_marble_pillar -blockus:chiseled_marble -blockus:marble_circle_pavement -c:marble_dusts -techreborn:marble_dust -c:marble_small_dusts -techreborn:marble_small_dust -c:meteor_metite_clusters -astromine:meteor_metite_cluster -c:meteor_metite_ores -astromine:meteor_metite_ore -c:metite_blocks -astromine:metite_block -c:metite_dusts -astromine:metite_dust -c:metite_gears -astromine:metite_gear -c:metite_ingots -astromine:metite_ingot -c:metite_nuggets -astromine:metite_nugget -2 -c:metite_ores -#c:meteor_metite_ores -#c:asteroid_metite_ores -c:metite_plates -astromine:metite_plates -c:metite_tiny_dusts -astromine:metite_tiny_dust -c:mixed_metal_ingots -techreborn:mixed_metal_ingot -c:netherite_blocks -minecraft:netherite_block -c:netherite_dusts -astromine:netherite_dust -c:netherite_gears -astromine:netherite_gear -c:netherite_ingots -minecraft:netherite_ingot -c:netherite_nuggets -astromine:netherite_nugget -c:netherite_plates -astromine:netherite_plates -c:netherite_scraps -minecraft:netherite_scrap -c:netherite_tiny_dusts -astromine:netherite_tiny_dust -c:netherrack_dusts -techreborn:netherrack_dust -c:netherrack_small_dusts -techreborn:netherrack_small_dust -c:nickel_blocks -techreborn:nickel_storage_block -c:nickel_dusts -techreborn:nickel_dust -c:nickel_ingots -techreborn:nickel_ingot -c:nickel_nuggets -techreborn:nickel_nugget -c:nickel_plates -techreborn:nickel_plate -c:nickel_small_dusts -techreborn:nickel_small_dust -c:obsidian_dusts -techreborn:obsidian_dust -c:obsidian_plates -techreborn:obsidian_plate -c:obsidian_small_dusts -techreborn:obsidian_small_dust -c:olivine_dusts -techreborn:olivine_dust -c:olivine_small_dusts -techreborn:olivine_small_dust -c:orange_dyes -minecraft:orange_dye -c:osmium_blocks -c:osmium_block -c:osmium_dusts -c:osmium_dust -c:osmium_gears -c:osmium_gear -c:osmium_ingots -c:osmium_ingot -c:osmium_nuggets -c:osmium_nugget -3 -c:osmium_ores -c:osmium_ore -c:osmium_nether_ore -c:osmium_end_ore -c:osmium_plates -c:osmium_plate -c:palladium_blocks -c:palladium_block -c:palladium_dusts -c:palladium_dust -c:palladium_gears -c:palladium_gear -c:palladium_ingots -c:palladium_ingot -c:palladium_nuggets -c:palladium_nugget -3 -c:palladium_ores -c:palladium_ore -c:palladium_nether_ore -c:palladium_end_ore -c:palladium_plates -c:palladium_plate -2 -c:peridot_blocks -c:peridot_block -techreborn:peridot_storage_block -2 -c:peridot_dusts -c:peridot_dust -techreborn:peridot_dust -c:peridot_gears -c:peridot_gear -c:peridot_gems -techreborn:peridot_gem -4 -c:peridot_ores -c:peridot_ore -c:peridot_nether_ore -c:peridot_end_ore -techreborn:peridot_ore -2 -c:peridot_plates -c:peridot_plate -techreborn:peridot_plate -c:peridot_small_dusts -techreborn:peridot_small_dust -c:peridots -c:peridot -c:phosphorous_dusts -techreborn:phosphorous_dust -c:phosphorous_small_dusts -techreborn:phosphorous_small_dust -10 -c:pickaxes -more_gems:citrine_pickaxe -more_gems:tourmaline_pickaxe -more_gems:amethyst_pickaxe -more_gems:emerald_pickaxe -more_gems:topaz_pickaxe -more_gems:alexandrite_pickaxe -more_gems:corundum_pickaxe -more_gems:sapphire_pickaxe -more_gems:ruby_pickaxe -more_gems:carbonado_pickaxe -c:pink_dyes -minecraft:pink_dye -2 -c:platinum_blocks -c:platinum_block -techreborn:platinum_storage_block -2 -c:platinum_dusts -c:platinum_dust -techreborn:platinum_dust -c:platinum_gears -c:platinum_gear -2 -c:platinum_ingots -c:platinum_ingot -techreborn:platinum_ingot -2 -c:platinum_nuggets -c:platinum_nugget -techreborn:platinum_nugget -3 -c:platinum_ores -c:platinum_ore -c:platinum_nether_ore -c:platinum_end_ore -2 -c:platinum_plates -c:platinum_plate -techreborn:platinum_plate -c:platinum_small_dusts -techreborn:platinum_small_dust -c:plutonium_blocks -c:plutonium_block -c:plutonium_dusts -c:plutonium_dust -c:plutonium_gears -c:plutonium_gear -c:plutonium_ingots -c:plutonium_ingot -c:plutonium_nuggets -c:plutonium_nugget -c:plutonium_plates -c:plutonium_plate -4 -c:protein -veggie_way:quinoa -veggie_way:lentil -veggie_way:soybean -veggie_way:cooked_tofu -c:purple_dyes -minecraft:purple_dye -c:pyrite_blocks -#c:fools_gold_blocks -2 -c:pyrite_dusts -#c:fools_gold_dusts -techreborn:pyrite_dust -c:pyrite_gears -#c:fools_gold_gears -c:pyrite_ingots -#c:fools_gold_ingots -c:pyrite_nuggets -#c:fools_gold_nuggets -c:pyrite_ores -techreborn:pyrite_ore -c:pyrite_plates -#c:fools_gold_plates -c:pyrite_small_dusts -techreborn:pyrite_small_dust -c:pyrite_tiny_dusts -#c:fools_gold_tiny_dusts -c:pyrope_dusts -techreborn:pyrope_dust -c:pyrope_small_dusts -techreborn:pyrope_small_dust -4 -c:quartz -minecraft:quartz -cinderscapes:smoky_quartz -cinderscapes:rose_quartz -cinderscapes:sulfur_quartz -3 -c:quartz_dusts -appliedenergistics2:nether_quartz_dust -astromine:quartz_dust -techreborn:quartz_dust -c:quartz_fragments -astromine:quartz_fragment -c:quartz_nuggets -#c:quartz_fragments -c:quartz_ores -minecraft:nether_quartz_ore -c:quartz_plates -techreborn:quartz_plate -c:quartz_small_dusts -techreborn:quartz_small_dust -c:quartz_tiny_dusts -astromine:quartz_tiny_dust -c:quinoa -veggie_way:quinoa_seeds -c:raw_netherite_dusts -astromine:raw_netherite_dust -c:raw_netherite_tiny_dusts -astromine:raw_netherite_tiny_dust -c:red_dyes -minecraft:red_dye -c:red_garnet_blocks -techreborn:red_garnet_storage_block -c:red_garnet_dusts -techreborn:red_garnet_dust -c:red_garnet_gems -techreborn:red_garnet_gem -c:red_garnet_plates -techreborn:red_garnet_plate -c:red_garnet_small_dusts -techreborn:red_garnet_small_dust -c:redstone_blocks -minecraft:redstone_block -c:redstone_dusts -minecraft:redstone -2 -c:redstone_ores -minecraft:redstone_ore -#c:asteroid_redstone_ores -c:redstone_plates -techreborn:redstone_plate -c:redstone_small_dusts -techreborn:redstone_small_dust -c:redstone_tiny_dusts -astromine:redstone_tiny_dust -c:refined_iron_blocks -techreborn:refined_iron_storage_block -c:refined_iron_ingots -techreborn:refined_iron_ingot -c:refined_iron_nuggets -techreborn:refined_iron_nugget -c:refined_iron_plates -techreborn:refined_iron_plate -c:rose_gold_blocks -astromine:rose_gold_block -c:rose_gold_dusts -astromine:rose_gold_dust -c:rose_gold_gears -astromine:rose_gold_gear -c:rose_gold_ingots -astromine:rose_gold_ingot -c:rose_gold_nuggets -astromine:rose_gold_nugget -c:rose_gold_plates -astromine:rose_gold_plates -c:rose_gold_tiny_dusts -astromine:rose_gold_tiny_dust -3 -c:rubies -c:ruby -earthtojavamobs:ruby -techreborn:ruby_gem -c:ruby -more_gems:ruby -3 -c:ruby_blocks -c:ruby_block -earthtojavamobs:ruby_block -techreborn:ruby_storage_block -2 -c:ruby_dusts -c:ruby_dust -techreborn:ruby_dust -c:ruby_gears -c:ruby_gear -5 -c:ruby_ores -c:ruby_ore -c:ruby_nether_ore -c:ruby_end_ore -earthtojavamobs:ruby_ore -techreborn:ruby_ore -2 -c:ruby_plates -c:ruby_plate -techreborn:ruby_plate -c:ruby_small_dusts -techreborn:ruby_small_dust -c:salt -epicurean:salt -c:saltpeter_dusts -techreborn:saltpeter_dust -c:saltpeter_small_dusts -techreborn:saltpeter_small_dust -2 -c:sand_blocks -minecraft:sand -minecraft:red_sand -c:sapphire -more_gems:sapphire -2 -c:sapphire_blocks -c:sapphire_block -techreborn:sapphire_storage_block -2 -c:sapphire_dusts -c:sapphire_dust -techreborn:sapphire_dust -c:sapphire_gears -c:sapphire_gear -4 -c:sapphire_ores -c:sapphire_ore -c:sapphire_nether_ore -c:sapphire_end_ore -techreborn:sapphire_ore -2 -c:sapphire_plates -c:sapphire_plate -techreborn:sapphire_plate -c:sapphire_small_dusts -techreborn:sapphire_small_dust -2 -c:sapphires -c:sapphire -techreborn:sapphire_gem -c:saw_dusts -techreborn:saw_dust -c:saw_small_dusts -techreborn:saw_small_dust -c:sheldonite_ores -techreborn:sheldonite_ore -c:silicon_plates -techreborn:silicon_plate -3 -c:silver_blocks -astromine:silver_block -c:silver_block -techreborn:silver_storage_block -3 -c:silver_dusts -astromine:silver_dust -c:silver_dust -techreborn:silver_dust -2 -c:silver_gears -astromine:silver_gear -c:silver_gear -4 -c:silver_ingots -astromine:silver_ingot -c:silver_ingot -ironchest,#c:silver_ingot -techreborn:silver_ingot -3 -c:silver_nuggets -astromine:silver_nugget -c:silver_nugget -techreborn:silver_nugget -6 -c:silver_ores -astromine:silver_ore -#c:asteroid_silver_ores -c:silver_ore -c:silver_nether_ore -c:silver_end_ore -techreborn:silver_ore -3 -c:silver_plates -astromine:silver_plates -c:silver_plate -techreborn:silver_plate -c:silver_small_dusts -techreborn:silver_small_dust -c:silver_tiny_dusts -astromine:silver_tiny_dust -c:silver_wires -astromine:silver_wire -c:sodalite_dusts -techreborn:sodalite_dust -c:sodalite_ores -techreborn:sodalite_ore -c:sodalite_small_dusts -techreborn:sodalite_small_dust -c:soybean -veggie_way:soybean -c:spessartine_dusts -techreborn:spessartine_dust -c:spessartine_small_dusts -techreborn:spessartine_small_dust -c:sphalerite_dusts -techreborn:sphalerite_dust -c:sphalerite_ores -techreborn:sphalerite_ore -c:sphalerite_small_dusts -techreborn:sphalerite_small_dust -3 -c:steel_blocks -astromine:steel_block -c:steel_block -techreborn:steel_storage_block -4 -c:steel_dusts -astromine:steel_dust -c:steel_dust -indrev:steel_dust -techreborn:steel_dust -2 -c:steel_gears -astromine:steel_gear -c:steel_gear -4 -c:steel_ingots -astromine:steel_ingot -c:steel_ingot -indrev:steel_ingot -techreborn:steel_ingot -3 -c:steel_nuggets -astromine:steel_nugget -c:steel_nugget -techreborn:steel_nugget -4 -c:steel_plates -astromine:steel_plates -c:steel_plate -indrev:steel_plate -techreborn:steel_plate -c:steel_small_dusts -techreborn:steel_small_dust -c:steel_tiny_dusts -astromine:steel_tiny_dust -c:steel_wires -astromine:steel_wire -c:stellum_blocks -astromine:stellum_block -c:stellum_dusts -astromine:stellum_dust -c:stellum_gears -astromine:stellum_gear -c:stellum_ingots -astromine:stellum_ingot -c:stellum_nuggets -astromine:stellum_nugget -c:stellum_ores -#c:asteroid_stellum_ores -c:stellum_plates -astromine:stellum_plates -c:stellum_tiny_dusts -astromine:stellum_tiny_dust -c:sterling_silver_blocks -astromine:sterling_silver_block -c:sterling_silver_dusts -astromine:sterling_silver_dust -c:sterling_silver_gears -astromine:sterling_silver_gear -c:sterling_silver_ingots -astromine:sterling_silver_ingot -c:sterling_silver_nuggets -astromine:sterling_silver_nugget -c:sterling_silver_plates -astromine:sterling_silver_plates -c:sterling_silver_tiny_dusts -astromine:sterling_silver_tiny_dust -c:stone_gears -c:stone_gear -c:stone_rod -adorn:stone_rod -4 -c:stones -minecraft:cobblestone -minecraft:granite -minecraft:diorite -minecraft:andesite -c:sulfur_dusts -techreborn:sulfur_dust -c:sulfur_ores -cinderscapes:sulfur_ore -c:sulfur_small_dusts -techreborn:sulfur_small_dust -c:sulfurs -cinderscapes:sulfur -17 -c:terracotta_blocks -minecraft:terracotta -minecraft:white_terracotta -minecraft:orange_terracotta -minecraft:magenta_terracotta -minecraft:light_blue_terracotta -minecraft:yellow_terracotta -minecraft:lime_terracotta -minecraft:pink_terracotta -minecraft:gray_terracotta -minecraft:light_gray_terracotta -minecraft:cyan_terracotta -minecraft:purple_terracotta -minecraft:blue_terracotta -minecraft:brown_terracotta -minecraft:green_terracotta -minecraft:red_terracotta -minecraft:black_terracotta -c:thorium_blocks -c:thorium_block -c:thorium_dusts -c:thorium_dust -c:thorium_gears -c:thorium_gear -c:thorium_ingots -c:thorium_ingot -c:thorium_nuggets -c:thorium_nugget -c:thorium_plates -c:thorium_plate -3 -c:tin_blocks -astromine:tin_block -c:tin_block -techreborn:tin_storage_block -4 -c:tin_dusts -astromine:tin_dust -c:tin_dust -indrev:tin_dust -techreborn:tin_dust -2 -c:tin_gears -astromine:tin_gear -c:tin_gear -4 -c:tin_ingots -astromine:tin_ingot -c:tin_ingot -indrev:tin_ingot -techreborn:tin_ingot -3 -c:tin_nuggets -astromine:tin_nugget -c:tin_nugget -techreborn:tin_nugget -7 -c:tin_ores -astromine:tin_ore -#c:asteroid_tin_ores -c:tin_ore -c:tin_nether_ore -c:tin_end_ore -indrev:tin_ore -techreborn:tin_ore -4 -c:tin_plates -astromine:tin_plates -c:tin_plate -indrev:tin_plate -techreborn:tin_plate -c:tin_small_dusts -techreborn:tin_small_dust -c:tin_tiny_dusts -astromine:tin_tiny_dust -c:tin_wires -astromine:tin_wire -2 -c:titanium_blocks -c:titanium_block -techreborn:titanium_storage_block -2 -c:titanium_dusts -c:titanium_dust -techreborn:titanium_dust -c:titanium_gears -c:titanium_gear -2 -c:titanium_ingots -c:titanium_ingot -techreborn:titanium_ingot -2 -c:titanium_nuggets -c:titanium_nugget -techreborn:titanium_nugget -3 -c:titanium_ores -c:titanium_ore -c:titanium_nether_ore -c:titanium_end_ore -2 -c:titanium_plates -c:titanium_plate -techreborn:titanium_plate -c:titanium_small_dusts -techreborn:titanium_small_dust -c:tofu -epicurean:tofu -c:topaz -more_gems:topaz -c:topaz_blocks -c:topaz_block -c:topaz_dusts -c:topaz_dust -c:topaz_gears -c:topaz_gear -3 -c:topaz_ores -c:topaz_ore -c:topaz_nether_ore -c:topaz_end_ore -c:topaz_plates -c:topaz_plate -c:topazes -c:topaz -c:tourmaline -more_gems:tourmaline -3 -c:tungsten_blocks -c:tungsten_block -endreborn:tungsten_block -techreborn:tungsten_storage_block -2 -c:tungsten_dusts -c:tungsten_dust -techreborn:tungsten_dust -c:tungsten_gears -c:tungsten_gear -3 -c:tungsten_ingots -c:tungsten_ingot -endreborn:tungsten_ingot -techreborn:tungsten_ingot -3 -c:tungsten_nuggets -c:tungsten_nugget -endreborn:tungsten_nugget -techreborn:tungsten_nugget -5 -c:tungsten_ores -c:tungsten_ore -c:tungsten_nether_ore -c:tungsten_end_ore -endreborn:end_tungsten_ore -techreborn:tungsten_ore -2 -c:tungsten_plates -c:tungsten_plate -techreborn:tungsten_plate -c:tungsten_small_dusts -techreborn:tungsten_small_dust -c:tungstensteel_blocks -techreborn:tungstensteel_storage_block -c:tungstensteel_ingots -techreborn:tungstensteel_ingot -c:tungstensteel_nuggets -techreborn:tungstensteel_nugget -c:tungstensteel_plates -techreborn:tungstensteel_plate -c:univite_blocks -astromine:univite_block -c:univite_dusts -astromine:univite_dust -c:univite_gears -astromine:univite_gear -c:univite_ingots -astromine:univite_ingot -c:univite_nuggets -astromine:univite_nugget -c:univite_plates -astromine:univite_plates -c:univite_tiny_dusts -astromine:univite_tiny_dust -c:uranium_blocks -c:uranium_block -c:uranium_dusts -c:uranium_dust -c:uranium_gears -c:uranium_gear -c:uranium_ingots -c:uranium_ingot -c:uranium_nuggets -c:uranium_nugget -3 -c:uranium_ores -c:uranium_ore -c:uranium_nether_ore -c:uranium_end_ore -c:uranium_plates -c:uranium_plate -c:uvarovite_dusts -techreborn:uvarovite_dust -c:uvarovite_small_dusts -techreborn:uvarovite_small_dust -3 -c:vegetables -minecraft:carrot -minecraft:dried_kelp -veggie_way:pumpkin_chunk -c:wheat_crops -minecraft:wheat -c:white_dyes -minecraft:white_dye -c:wood_gears -c:wood_gear -c:wood_plates -techreborn:wood_plate -c:wood_sticks -minecraft:stick -2 -c:wooden_chests -minecraft:chest -minecraft:trapped_chest -c:wooden_rods -minecraft:stick -c:yellow_dyes -minecraft:yellow_dye -c:yellow_garnet_blocks -techreborn:yellow_garnet_storage_block -c:yellow_garnet_dusts -techreborn:yellow_garnet_dust -c:yellow_garnet_gems -techreborn:yellow_garnet_gem -c:yellow_garnet_plates -techreborn:yellow_garnet_plate -c:yellow_garnet_small_dusts -techreborn:yellow_garnet_small_dust -2 -c:zinc_blocks -c:zinc_block -techreborn:zinc_storage_block -2 -c:zinc_dusts -c:zinc_dust -techreborn:zinc_dust -c:zinc_gears -c:zinc_gear -c:zinc_ingot -mechanized:zinc_ingot -3 -c:zinc_ingots -c:zinc_ingot -mechanized:zinc_ingot -techreborn:zinc_ingot -2 -c:zinc_nuggets -c:zinc_nugget -techreborn:zinc_nugget -c:zinc_ore -mechanized:zinc_ore -4 -c:zinc_ores -c:zinc_ore -c:zinc_nether_ore -c:zinc_end_ore -mechanized:zinc_ore -2 -c:zinc_plates -c:zinc_plate -techreborn:zinc_plate -c:zinc_small_dusts -techreborn:zinc_small_dust diff --git a/src/test/resources/test-rom/mcfly.lua b/src/test/resources/test-rom/mcfly.lua deleted file mode 100644 index 56a4430e8..000000000 --- a/src/test/resources/test-rom/mcfly.lua +++ /dev/null @@ -1,504 +0,0 @@ ---- A very basic test framework for ComputerCraft --- --- Like Busted (http://olivinelabs.com/busted/), but more memorable. --- --- @usage --- describe("something to test", function() --- it("some property", function() --- expect(some_function()):equals("What it should equal") --- end) --- end) - ---- Assert an argument to the given function has the specified type. --- --- @tparam string The function's name --- @tparam int The argument index to this function --- @tparam string The type this argument should have. May be 'value' for any --- non-nil value. --- @param val The value to check --- @raise If this value doesn't match the expected type. -local function check(func, arg, ty, val) - if ty == 'value' then - if val == nil then - error(('%s: bad argument #%d (got nil)'):format(func, arg), 3) - end - elseif type(val) ~= ty then - return error(('%s: bad argument #%d (expected %s, got %s)'):format(func, arg, ty, type(val)), 3) - end -end - -local active_stubs = {} - ---- Stub a global variable with a specific value --- --- @tparam string var The variable to stub --- @param value The value to stub it with -local function stub(tbl, var, value) - table.insert(active_stubs, { tbl = tbl, var = var, value = tbl[var] }) - _G[var] = value -end - - ---- Capture the current global state of the computer -local function push_state() - local stubs = active_stubs - active_stubs = {} - return { - term = term.current(), - input = io.input(), - output = io.output(), - stubs = stubs, - } -end - ---- Restore the global state of the computer to a previous version -local function pop_state(state) - for i = #active_stubs, 1, -1 do - local stub = active_stubs[i] - stub.tbl[stub.var] = stub.value - end - - active_stubs = state.stubs - - term.redirect(state.term) - io.input(state.input) - io.output(state.output) -end - -local error_mt = { __tostring = function(self) return self.message end } - ---- Attempt to execute the provided function, gathering a stack trace when it --- errors. --- --- @tparam --- @return[1] true --- @return[2] false --- @return[2] The error object -local function try(fn) - if not debug or not debug.traceback then - local ok, err = pcall(fn) - if ok or getmetatable(err) == error_mt then - return ok, err - else - return ok, setmetatable({ message = tostring(err) }, error_mt) - end - end - - local ok, err = xpcall(fn, function(err) - return { message = err, trace = debug.traceback(nil, 2) } - end) - - -- If we succeeded, propagate it - if ok then return ok, err end - - -- Error handling failed for some reason - just return a simpler error - if type(err) ~= "table" then - return ok, setmetatable({ message = tostring(err) }, error_mt) - end - - -- Find the common substring the errors' trace and the current one. Then - -- eliminate it. - local trace = debug.traceback() - for i = 1, #trace do - if trace:sub(-i) ~= err.trace:sub(-i) then - err.trace = err.trace:sub(1, -i) - break - end - end - - -- If we've received a rethrown error, copy - if getmetatable(err.message) == error_mt then - for k, v in pairs(err.message) do err[k] = v end - return ok, err - end - - return ok, setmetatable(err, error_mt) -end - ---- Fail a test with the given message --- --- @tparam string message The message to fail with --- @raises An error with the given message -local function fail(message) - check('fail', 1, 'string', message) - error(setmetatable({ message = message, fail = true }, error_mt)) -end - ---- Format an object in order to make it more readable --- --- @param value The value to format --- @treturn string The formatted value -local function format(value) - -- TODO: Look into something like mbs's pretty printer. - local ok, res = pcall(textutils.serialise, value) - if ok then return res else return tostring(value) end -end - -local expect_mt = {} -expect_mt.__index = expect_mt - ---- Assert that this expectation has the provided value --- --- @param value The value to require this expectation to be equal to --- @raises If the values are not equal -function expect_mt:equals(value) - if value ~= self.value then - fail(("Expected %s\n but got %s"):format(format(value), format(self.value))) - end - - return self -end -expect_mt.equal = expect_mt.equals -expect_mt.eq = expect_mt.equals - ---- Assert that this expectation does not equal the provided value --- --- @param value The value to require this expectation to not be equal to --- @raises If the values are equal -function expect_mt:not_equals(value) - if value == self.value then - fail(("Expected any value but %s"):format(format(value))) - end - - return self -end -expect_mt.not_equal = expect_mt.not_equals -expect_mt.ne = expect_mt.not_equals - ---- Assert that this expectation has something of the provided type --- --- @tparam string exp_type The type to require this expectation to have --- @raises If it does not have that thpe -function expect_mt:type(exp_type) - local actual_type = type(self.value) - if exp_type ~= actual_type then - fail(("Expected value of type %s\n got %s"):format(exp_type, actual_type)) - end - - return self -end - -local function matches(eq, exact, left, right) - if left == right then return true end - - local ty = type(left) - if ty ~= type(right) or ty ~= "table" then return false end - - -- If we've already explored/are exploring the left and right then return - if eq[left] and eq[left][right] then return true end - if not eq[left] then eq[left] = {[right] = true} else eq[left][right] = true end - if not eq[right] then eq[right] = {[left] = true} else eq[right][left] = true end - - -- Verify all pairs in left are equal to those in right - for k, v in pairs(left) do - if not matches(eq, exact, v, right[k]) then return false end - end - - if exact then - -- And verify all pairs in right are present in left - for k in pairs(right) do - if left[k] == nil then return false end - end - end - - return true -end - ---- Assert that this expectation is structurally equivalent to --- the provided object. --- --- @param value The value to check for structural equivalence --- @raises If they are not equivalent -function expect_mt:same(value) - if not matches({}, true, self.value, value) then - fail(("Expected %s\n but got %s"):format(format(value), format(self.value))) - end - - return self -end - ---- Assert that this expectation contains all fields mentioned --- in the provided object. --- --- @param value The value to check against --- @raises If this does not match the provided value -function expect_mt:matches(value) - if not matches({}, false, value, self.value) then - fail(("Expected %s\nto match %s"):format(format(self.value), format(value))) - end - - return self -end - -local expect = setmetatable( { - --- Construct an expectation on the error message calling this function - -- produces - -- - -- @tparam fun The function to call - -- @param ... The function arguments - -- @return The new expectation - error = function(fun, ...) - local ok, res = pcall(fun, ...) local _, line = pcall(error, "", 2) - if ok then fail("expected function to error") end - if res:sub(1, #line) == line then - res = res:sub(#line + 1) - elseif res:sub(1, 7) == "pcall: " then - res = res:sub(8) - end - return setmetatable({ value = res }, expect_mt) - end, -}, { - --- Construct a new expectation from the provided value - -- - -- @param value The value to apply assertions to - -- @return The new expectation - __call = function(_, value) - return setmetatable({ value = value }, expect_mt) - end -}) - ---- The stack of "describe"s. -local test_stack = { n = 0 } - ---- Whether we're now running tests, and so cannot run any more. -local tests_locked = false - ---- The list of tests that we'll run -local test_list, test_map, test_count = { }, { }, 0 - ---- Add a new test to our queue. --- --- @param test The descriptor of this test -local function do_test(test) - -- Set the name if it doesn't already exist - if not test.name then test.name = table.concat(test_stack, "\0", 1, test_stack.n) end - test_count = test_count + 1 - test_list[test_count] = test - test_map[test.name] = test_count -end - ---- Get the "friendly" name of this test. --- --- @treturn string This test's friendly name -local function test_name(test) return (test.name:gsub("\0", " \26 ")) end - ---- Describe something which will be tested, such as a function or situation --- --- @tparam string name The name of the object to test --- @tparam function body A function which describes the tests for this object. -local function describe(name, body) - check('describe', 1, 'string', name) - check('describe', 2, 'function', body) - if tests_locked then error("Cannot describe something while running tests", 2) end - - -- Push our name onto the stack, eval and pop it - local n = test_stack.n + 1 - test_stack[n], test_stack.n = name, n - - local ok, err = try(body) - - -- We count errors as a (failing) test. - if not ok then do_test { error = err } end - - test_stack.n = n - 1 -end - ---- Declare a single test within a context --- --- @tparam string name What you are testing --- @tparam function body A function which runs the test, failing if it does --- the assertions are not met. -local function it(name, body) - check('it', 1, 'string', name) - check('it', 2, 'function', body) - if tests_locked then error("Cannot create test while running tests", 2) end - - -- Push name onto the stack - local n = test_stack.n + 1 - test_stack[n], test_stack.n, tests_locked = name, n, true - - do_test { action = body } - - -- Pop the test from the stack - test_stack.n, tests_locked = n - 1, false -end - ---- Declare a single not-yet-implemented test --- --- @tparam string name What you really should be testing but aren't -local function pending(name) - check('it', 1, 'string', name) - if tests_locked then error("Cannot create test while running tests", 2) end - - local _, loc = pcall(error, "", 3) - loc = loc:gsub(":%s*$", "") - - local n = test_stack.n + 1 - test_stack[n], test_stack.n = name, n - do_test { pending = true, trace = loc } - test_stack.n = n - 1 -end - -local arg = ... -if arg == "--help" or arg == "-h" then - io.write("Usage: mcfly [DIR]\n") - io.write("\n") - io.write("Run tests in the provided DIRectory, or `spec` if not given.") - return -end - -local root_dir = shell.resolve(arg or "spec") -if not fs.isDir(root_dir) then - io.stderr:write(("%q is not a directory.\n"):format(root_dir)) - error() -end - -do - -- Load in the tests from all our files - local env = setmetatable({}, { __index = _ENV }) - - local function set_env(tbl) - for k in pairs(env) do env[k] = nil end - for k, v in pairs(tbl) do env[k] = v end - end - - -- When declaring tests, you shouldn't be able to use test methods - set_env { describe = describe, it = it, pending = pending } - - local suffix = "_spec.lua" - local function run_in(sub_dir) - for _, name in ipairs(fs.list(sub_dir)) do - local file = fs.combine(sub_dir, name) - if fs.isDir(file) then - run_in(file) - elseif file:sub(-#suffix) == suffix then - local fun, err = loadfile(file, env) - if not fun then - do_test { name = file:sub(#root_dir + 2), error = { message = err } } - else - local ok, err = try(fun) - if not ok then do_test { name = file:sub(#root_dir + 2), error = err } end - end - end - end - end - - run_in(root_dir) - - -- When running tests, you shouldn't be able to declare new ones. - set_env { expect = expect, fail = fail, stub = stub } -end - --- Error if we've found no tests -if test_count == 0 then - io.stderr:write(("Could not find any tests in %q\n"):format(root_dir)) - error() -end - --- The results of each test, as well as how many passed and the count. -local test_results, test_status, tests_run = { n = 0 }, {}, 0 - --- All possible test statuses -local statuses = { - pass = { desc = "Pass", col = colours.green, dot = "\7" }, -- Circle - fail = { desc = "Failed", col = colours.red, dot = "\4" }, -- Diamond - error = { desc = "Error", col = colours.magenta, dot = "\4" }, - pending = { desc = "Pending", col = colours.yellow, dot = "\186" }, -- Hollow circle -} - --- Set up each test status count. -for k in pairs(statuses) do test_status[k] = 0 end - ---- Do the actual running of our test -local function do_run(test) - -- If we're a pre-computed test, determine our status message. Otherwise, - -- skip. - local status, err - if test.pending then - status = "pending" - elseif test.error then - err = test.error - status = "error" - elseif test.action then - local state = push_state() - - local ok - ok, err = try(test.action) - status = ok and "pass" or (err.fail and "fail" or "error") - - pop_state(state) - end - - -- If we've a boolean status, then convert it into a string - if status == true then status = "pass" - elseif status == false then status = err.fail and "fail" or "error" - end - - tests_run = tests_run + 1 - test_status[status] = test_status[status] + 1 - test_results[tests_run] = { - status = status, name = test.name, - message = test.message or err and err.message, - trace = test.trace or err and err.trace, - } - - -- If we're running under howlci, then log some info. - if howlci then howlci.status(status, test_name(test)) end - if cct_test then cct_test.submit(test_results[tests_run]) end - - -- Print our progress dot - local data = statuses[status] - term.setTextColour(data.col) io.write(data.dot) - term.setTextColour(colours.white) -end - --- Loop over all our tests, running them as required. -if cct_test then - -- If we're within a cct_test environment, then submit them and wait on tests - -- to be run. - cct_test.start(test_map) - while true do - local _, name = os.pullEvent("cct_test_run") - if not name then break end - do_run(test_list[test_map[name]]) - end -else - for _, test in pairs(test_list) do do_run(test) end -end - --- Otherwise, display the results of each failure -io.write("\n\n") -for i = 1, tests_run do - local test = test_results[i] - if test.status ~= "pass" then - local status_data = statuses[test.status] - - term.setTextColour(status_data.col) - io.write(status_data.desc) - term.setTextColour(colours.white) - io.write(" \26 " .. test_name(test) .. "\n") - - if test.message then - io.write(" " .. test.message:gsub("\n", "\n ") .. "\n") - end - - if test.trace then - term.setTextColour(colours.lightGrey) - io.write(" " .. test.trace:gsub("\n", "\n ") .. "\n") - end - - io.write("\n") - end -end - --- And some summary statistics -local actual_count = tests_run - test_status.pending -local info = ("Ran %s test(s), of which %s passed (%g%%).") - :format(actual_count, test_status.pass, (test_status.pass / actual_count) * 100) - -if test_status.pending > 0 then - info = info .. (" Skipped %d pending test(s)."):format(test_status.pending) -end - -term.setTextColour(colours.white) io.write(info .. "\n") -if howlci then howlci.log("debug", info) sleep(3) end diff --git a/src/test/resources/test-rom/spec/apis/colors_spec.lua b/src/test/resources/test-rom/spec/apis/colors_spec.lua deleted file mode 100644 index c7505ca5a..000000000 --- a/src/test/resources/test-rom/spec/apis/colors_spec.lua +++ /dev/null @@ -1,92 +0,0 @@ -describe("The colors library", function() - describe("colors.combine", function() - it("validates arguments", function() - expect.error(colors.combine, 1, nil):eq("bad argument #2 (expected number, got nil)") - expect.error(colors.combine, 1, 1, nil):eq("bad argument #3 (expected number, got nil)") - end) - - it("combines colours", function() - expect(colors.combine()):eq(0) - expect(colors.combine(colors.red, colors.brown, colors.green)):eq(0x7000) - end) - end) - - describe("colors.subtract", function() - it("validates arguments", function() - expect.error(colors.subtract, nil):eq("bad argument #1 (expected number, got nil)") - expect.error(colors.subtract, 1, nil):eq("bad argument #2 (expected number, got nil)") - expect.error(colors.subtract, 1, 1, nil):eq("bad argument #3 (expected number, got nil)") - end) - - it("subtracts colours", function() - expect(colors.subtract(0x7000, colors.green)):equals(0x5000) - expect(colors.subtract(0x5000, colors.red)):equals(0x1000) - end) - it("does nothing when color is not present", function() - expect(colors.subtract(0x1000, colors.red)):equals(0x1000) - end) - it("accepts multiple arguments", function() - expect(colors.subtract(0x7000, colors.red, colors.green, colors.red)):equals(0x1000) - end) - end) - - describe("colors.test", function() - it("validates arguments", function() - expect.error(colors.test, nil):eq("bad argument #1 (expected number, got nil)") - expect.error(colors.test, 1, nil):eq("bad argument #2 (expected number, got nil)") - end) - - it("returns true when present", function() - expect(colors.test(0x7000, colors.green)):equals(true) - end) - it("returns false when absent", function() - expect(colors.test(0x5000, colors.green)):equals(false) - end) - it("allows multiple colors", function() - expect(colors.test(0x7000, 0x5000)):equals(true) - end) - end) - - describe("colors.packRGB", function() - it("validates arguments", function() - expect.error(colors.packRGB, nil):eq("bad argument #1 (expected number, got nil)") - expect.error(colors.packRGB, 1, nil):eq("bad argument #2 (expected number, got nil)") - expect.error(colors.packRGB, 1, 1, nil):eq("bad argument #3 (expected number, got nil)") - end) - - it("packs colours", function() - expect(colors.packRGB(0.3, 0.5, 0.6)):equals(0x4c7f99) - end) - end) - - describe("colors.unpackRGB", function() - it("validates arguments", function() - expect.error(colors.unpackRGB, nil):eq("bad argument #1 (expected number, got nil)") - end) - - it("unpacks colours", function() - expect({ colors.unpackRGB(0x4c7f99) }):same { 0x4c / 0xFF, 0x7f / 0xFF, 0.6 } - end) - end) - - it("colors.rgb8", function() - expect(colors.rgb8(0.3, 0.5, 0.6)):equals(0x4c7f99) - expect({ colors.rgb8(0x4c7f99) }):same { 0x4c / 0xFF, 0x7f / 0xFF, 0.6 } - end) - - describe("colors.toBlit", function() - it("validates arguments", function() - expect.error(colors.toBlit, nil):eq("bad argument #1 (expected number, got nil)") - end) - - it("converts all colors", function() - for i = 0, 15 do - expect(colors.toBlit(2 ^ i)):eq(string.format("%x", i)) - end - end) - - it("floors colors", function() - expect(colors.toBlit(16385)):eq("e") - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/apis/fs_spec.lua b/src/test/resources/test-rom/spec/apis/fs_spec.lua deleted file mode 100644 index 32503598e..000000000 --- a/src/test/resources/test-rom/spec/apis/fs_spec.lua +++ /dev/null @@ -1,222 +0,0 @@ -describe("The fs library", function() - describe("fs.complete", function() - it("validates arguments", function() - fs.complete("", "") - fs.complete("", "", true) - fs.complete("", "", nil, true) - - expect.error(fs.complete, nil):eq("bad argument #1 (expected string, got nil)") - expect.error(fs.complete, "", nil):eq("bad argument #2 (expected string, got nil)") - expect.error(fs.complete, "", "", 1):eq("bad argument #3 (expected boolean, got number)") - expect.error(fs.complete, "", "", true, 1):eq("bad argument #4 (expected boolean, got number)") - end) - end) - - describe("fs.isDriveRoot", function() - it("validates arguments", function() - fs.isDriveRoot("") - - expect.error(fs.isDriveRoot, nil):eq("bad argument #1 (expected string, got nil)") - end) - - it("correctly identifies drive roots", function() - expect(fs.isDriveRoot("/rom")):eq(true) - expect(fs.isDriveRoot("/")):eq(true) - expect(fs.isDriveRoot("/rom/startup.lua")):eq(false) - expect(fs.isDriveRoot("/rom/programs/delete.lua")):eq(false) - end) - end) - - describe("fs.list", function() - it("fails on files", function() - expect.error(fs.list, "rom/startup.lua"):eq("/rom/startup.lua: Not a directory") - expect.error(fs.list, "startup.lua"):eq("/startup.lua: Not a directory") - end) - - it("fails on non-existent nodes", function() - expect.error(fs.list, "rom/x"):eq("/rom/x: Not a directory") - expect.error(fs.list, "x"):eq("/x: Not a directory") - end) - end) - - describe("fs.combine", function() - it("removes . and ..", function() - expect(fs.combine("./a/b")):eq("a/b") - expect(fs.combine("a/b", "../c")):eq("a/c") - expect(fs.combine("a", "../c")):eq("c") - expect(fs.combine("a", "../../c")):eq("../c") - end) - - it("combines empty paths", function() - expect(fs.combine("a")):eq("a") - expect(fs.combine("a", "")):eq("a") - expect(fs.combine("", "a")):eq("a") - expect(fs.combine("a", "", "b", "c")):eq("a/b/c") - end) - end) - - describe("fs.getSize", function() - it("fails on non-existent nodes", function() - expect.error(fs.getSize, "rom/x"):eq("/rom/x: No such file") - expect.error(fs.getSize, "x"):eq("/x: No such file") - end) - end) - - describe("fs.open", function() - describe("reading", function() - it("fails on directories", function() - expect { fs.open("rom", "r") }:same { nil, "/rom: No such file" } - expect { fs.open("", "r") }:same { nil, "/: No such file" } - end) - - it("fails on non-existent nodes", function() - expect { fs.open("rom/x", "r") }:same { nil, "/rom/x: No such file" } - expect { fs.open("x", "r") }:same { nil, "/x: No such file" } - end) - - it("errors when closing twice", function() - local handle = fs.open("rom/startup.lua", "r") - handle.close() - expect.error(handle.close):eq("attempt to use a closed file") - end) - end) - - describe("reading in binary mode", function() - it("errors when closing twice", function() - local handle = fs.open("rom/startup.lua", "rb") - handle.close() - expect.error(handle.close):eq("attempt to use a closed file") - end) - end) - - describe("writing", function() - it("fails on directories", function() - expect { fs.open("", "w") }:same { nil, "/: Cannot write to directory" } - end) - - it("fails on read-only mounts", function() - expect { fs.open("rom/x", "w") }:same { nil, "/rom/x: Access denied" } - end) - - it("errors when closing twice", function() - local handle = fs.open("test-files/out.txt", "w") - handle.close() - expect.error(handle.close):eq("attempt to use a closed file") - end) - - it("fails gracefully when opening 'CON' on Windows", function() - local ok, err = fs.open("test-files/con", "w") - if ok then fs.delete("test-files/con") return end - - -- On my Windows/Java version the message appears to be "Incorrect function.". It may not be - -- consistent though, and honestly doesn't matter too much. - expect(err):str_match("^/test%-files/con: .*") - end) - end) - - describe("writing in binary mode", function() - it("errors when closing twice", function() - local handle = fs.open("test-files/out.txt", "wb") - handle.close() - expect.error(handle.close):eq("attempt to use a closed file") - end) - end) - - describe("appending", function() - it("fails on directories", function() - expect { fs.open("", "a") }:same { nil, "/: Cannot write to directory" } - end) - - it("fails on read-only mounts", function() - expect { fs.open("rom/x", "a") }:same { nil, "/rom/x: Access denied" } - end) - end) - end) - - describe("fs.makeDir", function() - it("fails on files", function() - expect.error(fs.makeDir, "startup.lua"):eq("/startup.lua: File exists") - end) - - it("fails on read-only mounts", function() - expect.error(fs.makeDir, "rom/x"):eq("/rom/x: Access denied") - end) - end) - - describe("fs.delete", function() - it("fails on read-only mounts", function() - expect.error(fs.delete, "rom/x"):eq("/rom/x: Access denied") - end) - end) - - describe("fs.copy", function() - it("fails on read-only mounts", function() - expect.error(fs.copy, "rom", "rom/startup"):eq("/rom/startup: Access denied") - end) - - it("fails to copy a folder inside itself", function() - fs.makeDir("some-folder") - expect.error(fs.copy, "some-folder", "some-folder/x"):eq("/some-folder: Can't copy a directory inside itself") - expect.error(fs.copy, "some-folder", "Some-Folder/x"):eq("/some-folder: Can't copy a directory inside itself") - end) - - it("copies folders", function() - fs.delete("some-folder") - fs.delete("another-folder") - - fs.makeDir("some-folder") - fs.copy("some-folder", "another-folder") - expect(fs.isDir("another-folder")):eq(true) - end) - end) - - describe("fs.move", function() - it("fails on read-only mounts", function() - expect.error(fs.move, "rom", "rom/move"):eq("Access denied") - expect.error(fs.move, "test-files", "rom/move"):eq("Access denied") - expect.error(fs.move, "rom", "test-files"):eq("Access denied") - end) - end) - - describe("fs.getCapacity", function() - it("returns nil on read-only mounts", function() - expect(fs.getCapacity("rom")):eq(nil) - end) - - it("returns the capacity on the root mount", function() - expect(fs.getCapacity("")):eq(10000000) - end) - end) - - describe("fs.attributes", function() - it("errors on non-existent files", function() - expect.error(fs.attributes, "xuxu_nao_existe"):eq("/xuxu_nao_existe: No such file") - end) - - it("returns information about read-only mounts", function() - expect(fs.attributes("rom")):matches { isDir = true, size = 0, isReadOnly = true } - end) - - it("returns information about files", function() - local now = os.epoch("utc") - - fs.delete("/tmp/basic-file") - local h = fs.open("/tmp/basic-file", "w") - h.write("A reasonably sized string") - h.close() - - local attributes = fs.attributes("tmp/basic-file") - expect(attributes):matches { isDir = false, size = 25, isReadOnly = false } - - if attributes.created - now >= 1000 then - fail(("Expected created time (%d) to be within 1000ms of now (%d"):format(attributes.created, now)) - end - - if attributes.modified - now >= 1000 then - fail(("Expected modified time (%d) to be within 1000ms of now (%d"):format(attributes.modified, now)) - end - - expect(attributes.modification):eq(attributes.modified) - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/apis/gps_spec.lua b/src/test/resources/test-rom/spec/apis/gps_spec.lua deleted file mode 100644 index 8d61a5c37..000000000 --- a/src/test/resources/test-rom/spec/apis/gps_spec.lua +++ /dev/null @@ -1,15 +0,0 @@ -describe("The gps library", function() - describe("gps.locate", function() - it("validates arguments", function() - stub(_G, "commands", { getBlockPosition = function() - end }) - - gps.locate() - gps.locate(1) - gps.locate(1, true) - - expect.error(gps.locate, ""):eq("bad argument #1 (expected number, got string)") - expect.error(gps.locate, 1, ""):eq("bad argument #2 (expected boolean, got string)") - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/apis/help_spec.lua b/src/test/resources/test-rom/spec/apis/help_spec.lua deleted file mode 100644 index d7ecb923f..000000000 --- a/src/test/resources/test-rom/spec/apis/help_spec.lua +++ /dev/null @@ -1,22 +0,0 @@ -describe("The help library", function() - describe("help.setPath", function() - it("validates arguments", function() - help.setPath(help.path()) - expect.error(help.setPath, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("help.lookup", function() - it("validates arguments", function() - help.lookup("") - expect.error(help.lookup, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("help.completeTopic", function() - it("validates arguments", function() - help.completeTopic("") - expect.error(help.completeTopic, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/apis/http_spec.lua b/src/test/resources/test-rom/spec/apis/http_spec.lua deleted file mode 100644 index a6774a48c..000000000 --- a/src/test/resources/test-rom/spec/apis/http_spec.lua +++ /dev/null @@ -1,19 +0,0 @@ -describe("The http library", function() - describe("http.checkURL", function() - it("accepts well formed domains", function() - expect({ http.checkURL("https://google.com")}):same({ true }) - end) - - it("rejects malformed URLs", function() - expect({ http.checkURL("google.com")}):same({ false, "Must specify http or https" }) - expect({ http.checkURL("https:google.com")}):same({ false, "URL malformed" }) - expect({ http.checkURL("https:/google.com")}):same({ false, "URL malformed" }) - expect({ http.checkURL("wss://google.com")}):same({ false, "Invalid protocol 'wss'" }) - end) - - it("rejects local domains", function() - expect({ http.checkURL("http://localhost")}):same({ false, "Domain not permitted" }) - expect({ http.checkURL("http://127.0.0.1")}):same({ false, "Domain not permitted" }) - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/apis/io_spec.lua b/src/test/resources/test-rom/spec/apis/io_spec.lua deleted file mode 100644 index 9dad5f7ec..000000000 --- a/src/test/resources/test-rom/spec/apis/io_spec.lua +++ /dev/null @@ -1,76 +0,0 @@ ---- Tests the io library is (mostly) consistent with PUC Lua. --- --- These tests are based on the tests for Lua 5.1 - -describe("The io library", function() - it("io.input on a handle returns that handle", function() - expect(io.input(io.stdin)):equals(io.stdin) - end) - - it("io.output on a handle returns that handle", function() - expect(io.output(io.stdout)):equals(io.stdout) - end) - - describe("io.type", function() - it("returns file on handles", function() - local handle = io.input() - expect(handle):type("table") - expect(io.type(handle)):equals("file") - end) - - it("returns nil on values", function() - expect(io.type(8)):equals(nil) - end) - - it("returns nil on tables", function() - expect(io.type(setmetatable({}, {}))):equals(nil) - end) - end) - - describe("io.lines", function() - it("validates arguments", function() - io.lines(nil) - expect.error(io.lines, ""):eq("/: No such file") - expect.error(io.lines, false):eq("bad argument #1 (expected string, got boolean)") - end) - end) - - describe("io.open", function() - it("validates arguments", function() - io.open("") - io.open("", "r") - - expect.error(io.open, nil):eq("bad argument #1 (expected string, got nil)") - expect.error(io.open, "", false):eq("bad argument #2 (expected string, got boolean)") - end) - - it("returns an error message on non-existent files", function() - local a, b = io.open('xuxu_nao_existe') - expect(a):equals(nil) - expect(b):type("string") - end) - end) - - pending("io.output allows redirecting and seeking", function() - fs.delete("/tmp/io_spec.txt") - - io.output("/tmp/io_spec.txt") - - expect(io.output()):not_equals(io.stdout) - - expect(io.output():seek()):equal(0) - assert(io.write("alo alo")) - expect(io.output():seek()):equal(#("alo alo")) - expect(io.output():seek("cur", -3)):equal(#("alo alo") - 3) - assert(io.write("joao")) - expect(io.output():seek("end"):equal(#("alo joao"))) - - expect(io.output():seek("set")):equal(0) - - assert(io.write('"�lo"', "{a}\n", "second line\n", "third line \n")) - assert(io.write('�fourth_line')) - - io.output(io.stdout) - expect(io.output()):equals(io.stdout) - end) -end) diff --git a/src/test/resources/test-rom/spec/apis/keys_spec.lua b/src/test/resources/test-rom/spec/apis/keys_spec.lua deleted file mode 100644 index 8983543bc..000000000 --- a/src/test/resources/test-rom/spec/apis/keys_spec.lua +++ /dev/null @@ -1,8 +0,0 @@ -describe("The keys library", function() - describe("keys.getName", function() - it("validates arguments", function() - keys.getName(1) - expect.error(keys.getName, nil):eq("bad argument #1 (expected number, got nil)") - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/apis/os_spec.lua b/src/test/resources/test-rom/spec/apis/os_spec.lua deleted file mode 100644 index 7fc1add53..000000000 --- a/src/test/resources/test-rom/spec/apis/os_spec.lua +++ /dev/null @@ -1,133 +0,0 @@ -describe("The os library", function() - describe("os.date and os.time", function() - it("round trips correctly", function() - local t = math.floor(os.epoch("local") / 1000) - local T = os.date("*t", t) - - expect(os.time(T)):eq(t) - end) - - it("dst field is guessed", function() - local T = os.date("*t") - local t = os.time(T) - expect(T.isdst):type("boolean") - T.isdst = nil - expect(os.time(T)):eq(t) -- if isdst is absent uses correct default - end) - - it("has 365 days in a year", function() - local T = os.date("*t") - local t = os.time(T) - T.year = T.year - 1 - local t1 = os.time(T) - local delta = (t - t1) / (24 * 3600) - 365 - -- allow for leap years - assert(math.abs(delta) < 2, ("expected abs(%d )< 2"):format(delta)) - end) - - it("os.date uses local timezone", function() - local epoch = os.epoch("local") / 1000 - local date = os.time(os.date("*t")) - assert(date - epoch <= 2, ("expected %d - %d <= 2, but not the case"):format(date, epoch)) - end) - end) - - describe("os.date", function() - it("formats as expected", function() - -- From the PUC Lua tests, hence the weird style - local t = os.epoch("local") - local T = os.date("*t", t) - - _G.T = T - loadstring(os.date([[assert(T.year==%Y and T.month==%m and T.day==%d and - T.hour==%H and T.min==%M and T.sec==%S and - T.wday==%w+1 and T.yday==%j and type(T.isdst) == 'boolean')]], t))() - - T = os.date("!*t", t) - _G.T = T - loadstring(os.date([[!assert(T.year==%Y and T.month==%m and T.day==%d and - T.hour==%H and T.min==%M and T.sec==%S and - T.wday==%w+1 and T.yday==%j and type(T.isdst) == 'boolean')]], t))() - end) - - describe("produces output consistent with PUC Lua", function() - -- Create a separate test for each code, just so it's easier to see what's broken - local t1 = os.time { year = 2000, month = 10, day = 1, hour = 23, min = 12, sec = 17 } - local function exp_code(code, value) - it(("for code '%s'"):format(code), function() - expect(os.date(code, t1)):eq(value) - end) - end - - exp_code("%a", "Sun") - exp_code("%A", "Sunday") - exp_code("%b", "Oct") - exp_code("%B", "October") - exp_code("%c", "Sun Oct 1 23:12:17 2000") - exp_code("%C", "20") - exp_code("%d", "01") - exp_code("%D", "10/01/00") - exp_code("%e", " 1") - exp_code("%F", "2000-10-01") - exp_code("%g", "00") - exp_code("%G", "2000") - exp_code("%h", "Oct") - exp_code("%H", "23") - exp_code("%I", "11") - exp_code("%j", "275") - exp_code("%m", "10") - exp_code("%M", "12") - exp_code("%n", "\n") - exp_code("%p", "PM") - exp_code("%r", "11:12:17 PM") - exp_code("%R", "23:12") - exp_code("%S", "17") - exp_code("%t", "\t") - exp_code("%T", "23:12:17") - exp_code("%u", "7") - exp_code("%U", "40") - exp_code("%V", "39") - exp_code("%w", "0") - exp_code("%W", "39") - exp_code("%x", "10/01/00") - exp_code("%X", "23:12:17") - exp_code("%y", "00") - exp_code("%Y", "2000") - exp_code("%%", "%") - - it("zones are numbers", function() - local zone = os.date("%z", t1) - if not zone:match("^[+-]%d%d%d%d$") then - error("Invalid zone: " .. zone) - end - end) - - it("zones id is made of letters", function() - local zone = os.date("%Z", t1) - if not zone:match("^%a%a+$") then - error("Non letter character in zone: " .. zone) - end - end) - end) - end) - - describe("os.time", function() - it("maps directly to seconds", function() - local t1 = os.time { year = 2000, month = 10, day = 1, hour = 23, min = 12, sec = 17 } - local t2 = os.time { year = 2000, month = 10, day = 1, hour = 23, min = 10, sec = 19 } - expect(t1 - t2):eq(60 * 2 - 2) - end) - end) - - describe("os.loadAPI", function() - it("validates arguments", function() - expect.error(os.loadAPI, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("os.unloadAPI", function() - it("validates arguments", function() - expect.error(os.loadAPI, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/apis/paintutils_spec.lua b/src/test/resources/test-rom/spec/apis/paintutils_spec.lua deleted file mode 100644 index f13bbcfd2..000000000 --- a/src/test/resources/test-rom/spec/apis/paintutils_spec.lua +++ /dev/null @@ -1,176 +0,0 @@ -local with_window = require "test_helpers".with_window - -describe("The paintutils library", function() - -- Verifies that a window's lines are equal to the given table of blit - -- strings ({{"text", "fg", "bg"}, {"text", "fg", "bg"}...}) - local function window_eq(w, state) - -- Verification of the size isn't really important in the tests, but - -- better safe than sorry. - local _, height = w.getSize() - expect(#state):eq(height) - - for line = 1, height do - expect({ w.getLine(line) }):same(state[line]) - end - end - - describe("paintutils.parseImage", function() - it("validates arguments", function() - paintutils.parseImage("") - expect.error(paintutils.parseImage, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("paintutils.loadImage", function() - it("validates arguments", function() - expect.error(paintutils.loadImage, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("paintutils.drawPixel", function() - it("validates arguments", function() - expect.error(paintutils.drawPixel, nil):eq("bad argument #1 (expected number, got nil)") - expect.error(paintutils.drawPixel, 1, nil):eq("bad argument #2 (expected number, got nil)") - expect.error(paintutils.drawPixel, 1, 1, false):eq("bad argument #3 (expected number, got boolean)") - end) - end) - - describe("paintutils.drawLine", function() - it("validates arguments", function() - expect.error(paintutils.drawLine, nil):eq("bad argument #1 (expected number, got nil)") - expect.error(paintutils.drawLine, 1, nil):eq("bad argument #2 (expected number, got nil)") - expect.error(paintutils.drawLine, 1, 1, nil):eq("bad argument #3 (expected number, got nil)") - expect.error(paintutils.drawLine, 1, 1, 1, nil):eq("bad argument #4 (expected number, got nil)") - expect.error(paintutils.drawLine, 1, 1, 1, 1, false):eq("bad argument #5 (expected number, got boolean)") - end) - - it("draws a line going across with custom colour", function() - local w = with_window(3, 2, function() - paintutils.drawLine(1, 1, 3, 1, colours.red) - end) - - window_eq(w, { - { " ", "000", "eee" }, - { " ", "000", "fff" }, - }) - end) - - it("draws a line going diagonally with term colour", function() - local w = with_window(3, 3, function() - term.setBackgroundColour(colours.red) - paintutils.drawLine(1, 1, 3, 3) - end) - - window_eq(w, { - { " ", "000", "eff" }, - { " ", "000", "fef" }, - { " ", "000", "ffe" }, - }) - end) - - it("draws a line going diagonally from bottom left", function() - local w = with_window(3, 3, function() - term.setBackgroundColour(colours.red) - paintutils.drawLine(1, 3, 3, 1) - end) - - window_eq(w, { - { " ", "000", "ffe" }, - { " ", "000", "fef" }, - { " ", "000", "eff" }, - }) - end) - end) - - describe("paintutils.drawBox", function() - it("validates arguments", function() - expect.error(paintutils.drawBox, nil):eq("bad argument #1 (expected number, got nil)") - expect.error(paintutils.drawBox, 1, nil):eq("bad argument #2 (expected number, got nil)") - expect.error(paintutils.drawBox, 1, 1, nil):eq("bad argument #3 (expected number, got nil)") - expect.error(paintutils.drawBox, 1, 1, 1, nil):eq("bad argument #4 (expected number, got nil)") - expect.error(paintutils.drawBox, 1, 1, 1, 1, false):eq("bad argument #5 (expected number, got boolean)") - end) - - it("draws a box with term colour", function() - local w = with_window(3, 3, function() - term.setBackgroundColour(colours.red) - paintutils.drawBox(1, 1, 3, 3) - end) - - window_eq(w, { - { " ", "eee", "eee" }, - { " ", "e0e", "efe" }, - { " ", "eee", "eee" }, - }) - end) - - it("draws a box with custom colour", function() - local w = with_window(3, 3, function() - paintutils.drawBox(1, 1, 3, 3, colours.red) - end) - - window_eq(w, { - { " ", "eee", "eee" }, - { " ", "e0e", "efe" }, - { " ", "eee", "eee" }, - }) - end) - - it("draws a box without overwriting existing content", function() - local w = with_window(3, 3, function() - term.setCursorPos(2, 2) - term.write("a") - paintutils.drawBox(1, 1, 3, 3, colours.red) - end) - - window_eq(w, { - { " ", "eee", "eee" }, - { " a ", "e0e", "efe" }, - { " ", "eee", "eee" }, - }) - end) - end) - - describe("paintutils.drawFilledBox", function() - it("validates arguments", function() - expect.error(paintutils.drawFilledBox, nil):eq("bad argument #1 (expected number, got nil)") - expect.error(paintutils.drawFilledBox, 1, nil):eq("bad argument #2 (expected number, got nil)") - expect.error(paintutils.drawFilledBox, 1, 1, nil):eq("bad argument #3 (expected number, got nil)") - expect.error(paintutils.drawFilledBox, 1, 1, 1, nil):eq("bad argument #4 (expected number, got nil)") - expect.error(paintutils.drawFilledBox, 1, 1, 1, 1, false):eq("bad argument #5 (expected number, got boolean)") - end) - - it("draws a filled box with term colour", function() - local w = with_window(3, 3, function() - term.setBackgroundColour(colours.red) - paintutils.drawFilledBox(1, 1, 3, 3) - end) - - window_eq(w, { - { " ", "eee", "eee" }, - { " ", "eee", "eee" }, - { " ", "eee", "eee" }, - }) - end) - - it("draws a filled box with custom colour", function() - local w = with_window(3, 3, function() - paintutils.drawFilledBox(1, 1, 3, 3, colours.red) - end) - - window_eq(w, { - { " ", "eee", "eee" }, - { " ", "eee", "eee" }, - { " ", "eee", "eee" }, - }) - end) - end) - - describe("paintutils.drawImage", function() - it("validates arguments", function() - expect.error(paintutils.drawImage, nil):eq("bad argument #1 (expected table, got nil)") - expect.error(paintutils.drawImage, {}, nil):eq("bad argument #2 (expected number, got nil)") - expect.error(paintutils.drawImage, {}, 1, nil):eq("bad argument #3 (expected number, got nil)") - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/apis/peripheral_spec.lua b/src/test/resources/test-rom/spec/apis/peripheral_spec.lua deleted file mode 100644 index 8fca583e1..000000000 --- a/src/test/resources/test-rom/spec/apis/peripheral_spec.lua +++ /dev/null @@ -1,47 +0,0 @@ -describe("The peripheral library", function() - describe("peripheral.isPresent", function() - it("validates arguments", function() - peripheral.isPresent("") - expect.error(peripheral.isPresent, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("peripheral.getType", function() - it("validates arguments", function() - peripheral.getType("") - expect.error(peripheral.getType, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("peripheral.getMethods", function() - it("validates arguments", function() - peripheral.getMethods("") - expect.error(peripheral.getMethods, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("peripheral.call", function() - it("validates arguments", function() - peripheral.call("", "") - expect.error(peripheral.call, nil):eq("bad argument #1 (expected string, got nil)") - expect.error(peripheral.call, "", nil):eq("bad argument #2 (expected string, got nil)") - end) - end) - - describe("peripheral.wrap", function() - it("validates arguments", function() - peripheral.wrap("") - expect.error(peripheral.wrap, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("peripheral.find", function() - it("validates arguments", function() - peripheral.find("") - peripheral.find("", function() - end) - expect.error(peripheral.find, nil):eq("bad argument #1 (expected string, got nil)") - expect.error(peripheral.find, "", false):eq("bad argument #2 (expected function, got boolean)") - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/apis/rednet_spec.lua b/src/test/resources/test-rom/spec/apis/rednet_spec.lua deleted file mode 100644 index f6c942e33..000000000 --- a/src/test/resources/test-rom/spec/apis/rednet_spec.lua +++ /dev/null @@ -1,86 +0,0 @@ -describe("The rednet library", function() - describe("rednet.open", function() - it("validates arguments", function() - expect.error(rednet.open, nil):eq("bad argument #1 (expected string, got nil)") - end) - - it("requires a modem to be present", function() - expect.error(rednet.open, "not_there"):eq("No such modem: not_there") - end) - end) - - describe("rednet.close", function() - it("validates arguments", function() - rednet.close() - expect.error(rednet.close, 1):eq("bad argument #1 (expected string, got number)") - expect.error(rednet.close, false):eq("bad argument #1 (expected string, got boolean)") - end) - - it("requires a modem to be present", function() - expect.error(rednet.close, "not_there"):eq("No such modem: not_there") - end) - end) - - describe("rednet.isOpen", function() - it("validates arguments", function() - rednet.isOpen() - rednet.isOpen("") - expect.error(rednet.isOpen, 1):eq("bad argument #1 (expected string, got number)") - expect.error(rednet.isOpen, false):eq("bad argument #1 (expected string, got boolean)") - end) - end) - - describe("rednet.send", function() - it("validates arguments", function() - rednet.send(1) - rednet.send(1, nil, "") - expect.error(rednet.send, nil):eq("bad argument #1 (expected number, got nil)") - expect.error(rednet.send, 1, nil, false):eq("bad argument #3 (expected string, got boolean)") - end) - end) - - describe("rednet.broadcast", function() - it("validates arguments", function() - rednet.broadcast(nil) - rednet.broadcast(nil, "") - expect.error(rednet.broadcast, nil, false):eq("bad argument #2 (expected string, got boolean)") - end) - end) - - describe("rednet.receive", function() - it("validates arguments", function() - expect.error(rednet.receive, false):eq("bad argument #1 (expected string, got boolean)") - expect.error(rednet.receive, "", false):eq("bad argument #2 (expected number, got boolean)") - end) - end) - - describe("rednet.host", function() - it("validates arguments", function() - expect.error(rednet.host, "", "localhost"):eq("Reserved hostname") - expect.error(rednet.host, nil):eq("bad argument #1 (expected string, got nil)") - expect.error(rednet.host, "", nil):eq("bad argument #2 (expected string, got nil)") - end) - end) - - describe("rednet.unhost", function() - it("validates arguments", function() - rednet.unhost("") - expect.error(rednet.unhost, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("rednet.lookup", function() - it("validates arguments", function() - expect.error(rednet.lookup, nil):eq("bad argument #1 (expected string, got nil)") - expect.error(rednet.lookup, "", false):eq("bad argument #2 (expected string, got boolean)") - end) - - it("gets a locally hosted protocol", function() - rednet.host("a_protocol", "a_hostname") - - expect(rednet.lookup("a_protocol")):eq(os.getComputerID()) - expect(rednet.lookup("a_protocol", "localhost")):eq(os.getComputerID()) - expect(rednet.lookup("a_protocol", "a_hostname")):eq(os.getComputerID()) - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/apis/settings_spec.lua b/src/test/resources/test-rom/spec/apis/settings_spec.lua deleted file mode 100644 index b54e24e67..000000000 --- a/src/test/resources/test-rom/spec/apis/settings_spec.lua +++ /dev/null @@ -1,43 +0,0 @@ -describe("The settings library", function() - describe("settings.set", function() - it("validates arguments", function() - settings.set("test", 1) - settings.set("test", "") - settings.set("test", {}) - settings.set("test", false) - - expect.error(settings.set, nil):eq("bad argument #1 (expected string, got nil)") - expect.error(settings.set, "", nil):eq("bad argument #2 (expected number, string, boolean or table, got nil)") - end) - - it("prevents storing unserialisable types", function() - expect.error(settings.set, "", { print }):eq("Cannot serialize type function") - end) - end) - - describe("settings.get", function() - it("validates arguments", function() - settings.get("test") - expect.error(settings.get, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("settings.unset", function() - it("validates arguments", function() - settings.unset("test") - expect.error(settings.unset, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("settings.load", function() - it("validates arguments", function() - expect.error(settings.load, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("settings.save", function() - it("validates arguments", function() - expect.error(settings.save, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/apis/term_spec.lua b/src/test/resources/test-rom/spec/apis/term_spec.lua deleted file mode 100644 index 769fcb867..000000000 --- a/src/test/resources/test-rom/spec/apis/term_spec.lua +++ /dev/null @@ -1,12 +0,0 @@ -describe("The term library", function() - describe("term.redirect", function() - it("validates arguments", function() - expect.error(term.redirect, nil):eq("bad argument #1 (expected table, got nil)") - end) - - it("prevents redirecting to term", function() - expect.error(term.redirect, term) - :eq("term is not a recommended redirect target, try term.current() instead") - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/apis/textutils_spec.lua b/src/test/resources/test-rom/spec/apis/textutils_spec.lua deleted file mode 100644 index 6e1ba2bb7..000000000 --- a/src/test/resources/test-rom/spec/apis/textutils_spec.lua +++ /dev/null @@ -1,189 +0,0 @@ -describe("The textutils library", function() - describe("textutils.slowWrite", function() - it("validates arguments", function() - expect.error(textutils.slowWrite, nil, false):eq("bad argument #2 (expected number, got boolean)") - end) - end) - - describe("textutils.formatTime", function() - it("validates arguments", function() - textutils.formatTime(0) - textutils.formatTime(0, false) - expect.error(textutils.formatTime, nil):eq("bad argument #1 (expected number, got nil)") - expect.error(textutils.formatTime, 1, 1):eq("bad argument #2 (expected boolean, got number)") - end) - end) - - describe("textutils.pagedPrint", function() - it("validates arguments", function() - expect.error(textutils.pagedPrint, nil, false):eq("bad argument #2 (expected number, got boolean)") - end) - end) - - describe("textutils.tabulate", function() - it("validates arguments", function() - term.redirect(window.create(term.current(), 1, 1, 5, 5, false)) - - textutils.tabulate() - textutils.tabulate({ "test" }) - textutils.tabulate(colors.white) - - expect.error(textutils.tabulate, nil):eq("bad argument #1 (expected number or table, got nil)") - expect.error(textutils.tabulate, { "test" }, nil):eq("bad argument #2 (expected number or table, got nil)") - end) - end) - - describe("textutils.pagedTabulate", function() - it("validates arguments", function() - term.redirect(window.create(term.current(), 1, 1, 5, 5, false)) - - textutils.pagedTabulate() - textutils.pagedTabulate({ "test" }) - textutils.pagedTabulate(colors.white) - - expect.error(textutils.pagedTabulate, nil):eq("bad argument #1 (expected number or table, got nil)") - expect.error(textutils.pagedTabulate, { "test" }, nil):eq("bad argument #2 (expected number or table, got nil)") - end) - end) - - describe("textutils.empty_json_array", function() - it("is immutable", function() - expect.error(function() textutils.empty_json_array[1] = true end) - :eq("textutils_spec.lua:51: attempt to mutate textutils.empty_json_array") - end) - end) - - describe("textutils.unserialise", function() - it("validates arguments", function() - textutils.unserialise("") - expect.error(textutils.unserialise, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("textutils.serialiseJSON", function() - it("validates arguments", function() - textutils.serialiseJSON("") - textutils.serialiseJSON(1) - textutils.serialiseJSON({}) - textutils.serialiseJSON(false) - textutils.serialiseJSON("", true) - expect.error(textutils.serialiseJSON, nil):eq("bad argument #1 (expected table, string, number or boolean, got nil)") - expect.error(textutils.serialiseJSON, "", 1):eq("bad argument #2 (expected boolean, got number)") - end) - - it("serializes empty arrays", function() - expect(textutils.serializeJSON(textutils.empty_json_array)):eq("[]") - end) - - it("serializes null", function() - expect(textutils.serializeJSON(textutils.json_null)):eq("null") - end) - - it("serializes strings", function() - expect(textutils.serializeJSON('a')):eq('"a"') - expect(textutils.serializeJSON('"')):eq('"\\""') - expect(textutils.serializeJSON('\\')):eq('"\\\\"') - expect(textutils.serializeJSON('/')):eq('"/"') - expect(textutils.serializeJSON('\b')):eq('"\\b"') - expect(textutils.serializeJSON('\n')):eq('"\\n"') - expect(textutils.serializeJSON(string.char(0))):eq('"\\u0000"') - expect(textutils.serializeJSON(string.char(0x0A))):eq('"\\n"') - expect(textutils.serializeJSON(string.char(0x1D))):eq('"\\u001D"') - expect(textutils.serializeJSON(string.char(0x81))):eq('"\\u0081"') - expect(textutils.serializeJSON(string.char(0xFF))):eq('"\\u00FF"') - end) - - it("serializes arrays until the last index with content", function() - expect(textutils.serializeJSON({ 5, "test", nil, nil, 7 })):eq('[5,"test",null,null,7]') - expect(textutils.serializeJSON({ 5, "test", nil, nil, textutils.json_null })):eq('[5,"test",null,null,null]') - expect(textutils.serializeJSON({ nil, nil, nil, nil, "text" })):eq('[null,null,null,null,"text"]') - end) - end) - - describe("textutils.unserializeJSON", function() - describe("parses", function() - it("a list of primitives", function() - expect(textutils.unserializeJSON('[1, true, false, "hello"]')):same { 1, true, false, "hello" } - end) - - it("null when parse_null is true", function() - expect(textutils.unserializeJSON("null", { parse_null = true })):eq(textutils.json_null) - end) - - it("null when parse_null is false", function() - expect(textutils.unserializeJSON("null", { parse_null = false })):eq(nil) - end) - - it("an empty array", function() - expect(textutils.unserializeJSON("[]", { parse_null = false })):eq(textutils.empty_json_array) - end) - - it("basic objects", function() - expect(textutils.unserializeJSON([[{ "a": 1, "b":2 }]])):same { a = 1, b = 2 } - end) - end) - - describe("parses using NBT-style syntax", function() - local function exp(x) - local res, err = textutils.unserializeJSON(x, { nbt_style = true }) - if not res then error(err, 2) end - return expect(res) - end - it("basic objects", function() - exp([[{ a: 1, b:2 }]]):same { a = 1, b = 2 } - end) - - it("suffixed numbers", function() - exp("1b"):eq(1) - exp("1.1d"):eq(1.1) - end) - - it("strings", function() - exp("'123'"):eq("123") - exp("\"123\""):eq("123") - end) - - it("typed arrays", function() - exp("[B; 1, 2, 3]"):same { 1, 2, 3 } - exp("[B;]"):same {} - end) - end) - - describe("passes nst/JSONTestSuite", function() - local search_path = "test-rom/data/json-parsing" - local skip = dofile(search_path .. "/skip.lua") - for _, file in pairs(fs.find(search_path .. "/*.json")) do - local name = fs.getName(file):sub(1, -6); - (skip[name] and pending or it)(name, function() - local h = io.open(file, "r") - local contents = h:read("*a") - h:close() - - local res, err = textutils.unserializeJSON(contents) - local kind = fs.getName(file):sub(1, 1) - if kind == "n" then - expect(res):eq(nil) - elseif kind == "y" then - if err ~= nil then fail("Expected test to pass, but failed with " .. err) end - end - end) - end - end) - end) - - describe("textutils.urlEncode", function() - it("validates arguments", function() - textutils.urlEncode("") - expect.error(textutils.urlEncode, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("textutils.complete", function() - it("validates arguments", function() - textutils.complete("pri") - textutils.complete("pri", _G) - expect.error(textutils.complete, nil):eq("bad argument #1 (expected string, got nil)") - expect.error(textutils.complete, "", false):eq("bad argument #2 (expected table, got boolean)") - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/apis/window_spec.lua b/src/test/resources/test-rom/spec/apis/window_spec.lua deleted file mode 100644 index d1861eef2..000000000 --- a/src/test/resources/test-rom/spec/apis/window_spec.lua +++ /dev/null @@ -1,173 +0,0 @@ -describe("The window library", function() - local function mk() - return window.create(term.current(), 1, 1, 5, 5, false) - end - - describe("window.create", function() - it("validates arguments", function() - local r = mk() - window.create(r, 1, 1, 5, 5) - window.create(r, 1, 1, 5, 5, false) - - expect.error(window.create, nil):eq("bad argument #1 (expected table, got nil)") - expect.error(window.create, r, nil):eq("bad argument #2 (expected number, got nil)") - expect.error(window.create, r, 1, nil):eq("bad argument #3 (expected number, got nil)") - expect.error(window.create, r, 1, 1, nil):eq("bad argument #4 (expected number, got nil)") - expect.error(window.create, r, 1, 1, 1, nil):eq("bad argument #5 (expected number, got nil)") - expect.error(window.create, r, 1, 1, 1, 1, ""):eq("bad argument #6 (expected boolean, got string)") - end) - end) - - describe("Window.blit", function() - it("validates arguments", function() - local w = mk() - w.blit("a", "a", "a") - - expect.error(w.blit, nil):eq("bad argument #1 (expected string, got nil)") - expect.error(w.blit, "", nil):eq("bad argument #2 (expected string, got nil)") - expect.error(w.blit, "", "", nil):eq("bad argument #3 (expected string, got nil)") - expect.error(w.blit, "", "", "a"):eq("Arguments must be the same length") - end) - end) - - describe("Window.setCursorPos", function() - it("validates arguments", function() - local w = mk() - w.setCursorPos(1, 1) - - expect.error(w.setCursorPos, nil):eq("bad argument #1 (expected number, got nil)") - expect.error(w.setCursorPos, 1, nil):eq("bad argument #2 (expected number, got nil)") - end) - end) - - describe("Window.setCursorBlink", function() - it("validates arguments", function() - local w = mk() - w.setCursorBlink(false) - expect.error(w.setCursorBlink, nil):eq("bad argument #1 (expected boolean, got nil)") - end) - end) - - describe("Window.setTextColour", function() - it("validates arguments", function() - local w = mk() - w.setTextColour(colors.white) - - expect.error(w.setTextColour, nil):eq("bad argument #1 (expected number, got nil)") - expect.error(w.setTextColour, -5):eq("Invalid color (got -5)") - end) - end) - - describe("Window.setPaletteColour", function() - it("validates arguments", function() - local w = mk() - w.setPaletteColour(colors.white, 0, 0, 0) - w.setPaletteColour(colors.white, 0x000000) - - expect.error(w.setPaletteColour, nil):eq("bad argument #1 (expected number, got nil)") - expect.error(w.setPaletteColour, -5):eq("Invalid color (got -5)") - expect.error(w.setPaletteColour, colors.white):eq("bad argument #2 (expected number, got nil)") - expect.error(w.setPaletteColour, colors.white, 1, false):eq("bad argument #3 (expected number, got boolean)") - expect.error(w.setPaletteColour, colors.white, 1, nil, 1):eq("bad argument #3 (expected number, got nil)") - expect.error(w.setPaletteColour, colors.white, 1, 1, nil):eq("bad argument #4 (expected number, got nil)") - end) - end) - - describe("Window.getPaletteColour", function() - it("validates arguments", function() - local w = mk() - w.getPaletteColour(colors.white) - expect.error(w.getPaletteColour, nil):eq("bad argument #1 (expected number, got nil)") - expect.error(w.getPaletteColour, -5):eq("Invalid color (got -5)") - end) - end) - - describe("Window.setBackgroundColour", function() - it("validates arguments", function() - local w = mk() - w.setBackgroundColour(colors.white) - - expect.error(w.setBackgroundColour, nil):eq("bad argument #1 (expected number, got nil)") - expect.error(w.setBackgroundColour, -5):eq("Invalid color (got -5)") - end) - end) - - describe("Window.scroll", function() - it("validates arguments", function() - local w = mk() - w.scroll(0) - expect.error(w.scroll, nil):eq("bad argument #1 (expected number, got nil)") - end) - end) - - describe("Window.setVisible", function() - it("validates arguments", function() - local w = mk() - w.setVisible(false) - expect.error(w.setVisible, nil):eq("bad argument #1 (expected boolean, got nil)") - end) - end) - - describe("Window.reposition", function() - it("validates arguments", function() - local w = mk() - w.reposition(1, 1) - w.reposition(1, 1, 5, 5) - expect.error(w.reposition, nil):eq("bad argument #1 (expected number, got nil)") - expect.error(w.reposition, 1, nil):eq("bad argument #2 (expected number, got nil)") - expect.error(w.reposition, 1, 1, false, 1):eq("bad argument #3 (expected number, got boolean)") - expect.error(w.reposition, 1, 1, nil, 1):eq("bad argument #3 (expected number, got nil)") - expect.error(w.reposition, 1, 1, 1, nil):eq("bad argument #4 (expected number, got nil)") - expect.error(w.reposition, 1, 1, 1, 1, true):eq("bad argument #5 (expected table, got boolean)") - end) - - it("can change the buffer", function() - local a, b = mk(), mk() - local target = window.create(a, 1, 1, a.getSize()) - - target.write("Test") - expect((a.getLine(1))):equal("Test ") - expect({ a.getCursorPos() }):same { 5, 1 } - - target.reposition(1, 1, nil, nil, b) - - target.redraw() - expect((a.getLine(1))):equal("Test ") - expect({ a.getCursorPos() }):same { 5, 1 } - - target.setCursorPos(1, 1) target.write("More") - expect((a.getLine(1))):equal("Test ") - expect((b.getLine(1))):equal("More ") - end) - end) - - describe("Window.getLine", function() - it("validates arguments", function() - local w = mk() - w.getLine(1) - local _, y = w.getSize() - expect.error(w.getLine, nil):eq("bad argument #1 (expected number, got nil)") - expect.error(w.getLine, 0):eq("Line is out of range.") - expect.error(w.getLine, y + 1):eq("Line is out of range.") - end) - - it("provides a line's contents", function() - local w = mk() - w.blit("test", "aaaa", "4444") - expect({ w.getLine(1) }):same { "test ", "aaaa0", "4444f" } - end) - end) - describe("Window.setVisible", function() - it("validates arguments", function() - local w = mk() - expect.error(w.setVisible, nil):eq("bad argument #1 (expected boolean, got nil)") - end) - end) - describe("Window.isVisible", function() - it("gets window visibility", function() - local w = mk() - w.setVisible(false) - expect(w.isVisible()):same(false) - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/base_spec.lua b/src/test/resources/test-rom/spec/base_spec.lua deleted file mode 100644 index 191d87eab..000000000 --- a/src/test/resources/test-rom/spec/base_spec.lua +++ /dev/null @@ -1,123 +0,0 @@ -describe("The Lua base library", function() - describe("expect", function() - local e = _G["~expect"] - - it("checks a single type", function() - expect(e(1, "test", "string")):eq(true) - expect(e(1, 2, "number")):eq(true) - - expect.error(e, 1, nil, "string"):eq("bad argument #1 (expected string, got nil)") - expect.error(e, 2, 1, "nil"):eq("bad argument #2 (expected nil, got number)") - end) - - it("checks multiple types", function() - expect(e(1, "test", "string", "number")):eq(true) - expect(e(1, 2, "string", "number")):eq(true) - - expect.error(e, 1, nil, "string", "number"):eq("bad argument #1 (expected string or number, got nil)") - expect.error(e, 2, false, "string", "table", "number", "nil") - :eq("bad argument #2 (expected string, table or number, got boolean)") - end) - - it("includes the function name", function() - local function worker() - expect(e(1, nil, "string")):eq(true) - end - local function trampoline() - worker() - end - - expect.error(trampoline):eq("base_spec.lua:27: bad argument #1 to 'worker' (expected string, got nil)") - end) - end) - - describe("sleep", function() - it("validates arguments", function() - sleep(0) - sleep(nil) - - expect.error(sleep, false):eq("bad argument #1 (expected number, got boolean)") - end) - end) - - describe("write", function() - it("validates arguments", function() - write("") - expect.error(write, nil):eq("bad argument #1 (expected string or number, got nil)") - end) - end) - - describe("loadfile", function() - it("validates arguments", function() - loadfile("") - loadfile("", {}) - - expect.error(loadfile, nil):eq("bad argument #1 (expected string, got nil)") - expect.error(loadfile, "", false):eq("bad argument #2 (expected table, got boolean)") - end) - - it("prefixes the filename with @", function() - local info = debug.getinfo(loadfile("/rom/startup.lua"), "S") - expect(info):matches { short_src = "startup.lua", source = "@startup.lua" } - end) - end) - - describe("dofile", function() - it("validates arguments", function() - expect.error(dofile, ""):eq("File not found") - expect.error(dofile, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("loadstring", function() - it("prefixes the chunk name with '='", function() - local info = debug.getinfo(loadstring("return 1", "name"), "S") - expect(info):matches { short_src = "name", source = "=name" } - end) - - it("does not prefix for unnamed chunks", function() - local info = debug.getinfo(loadstring("return 1"), "S") - expect(info):matches { short_src = '[string "return 1"]', source = "return 1", } - end) - - it("does not prefix when already prefixed", function() - local info = debug.getinfo(loadstring("return 1", "@file.lua"), "S") - expect(info):matches { short_src = "file.lua", source = "@file.lua" } - - info = debug.getinfo(loadstring("return 1", "=file.lua"), "S") - expect(info):matches { short_src = "file.lua", source = "=file.lua" } - end) - end) - - describe("load", function() - it("validates arguments", function() - load("") - load(function() - end) - load("", "") - load("", "", "") - load("", "", "", _ENV) - - expect.error(load, nil):eq("bad argument #1 (expected function or string, got nil)") - expect.error(load, "", false):eq("bad argument #2 (expected string, got boolean)") - expect.error(load, "", "", false):eq("bad argument #3 (expected string, got boolean)") - expect.error(load, "", "", "", false):eq("bad argument #4 (expected table, got boolean)") - end) - - local function generator(parts) - return coroutine.wrap(function() - for i = 1, #parts do - coroutine.yield(parts[i]) - end - end) - end - - it("does not prefix the chunk name with '='", function() - local info = debug.getinfo(load("return 1", "name"), "S") - expect(info):matches { short_src = "[string \"name\"]", source = "name" } - - info = debug.getinfo(load(generator { "return 1" }, "name"), "S") - expect(info):matches { short_src = "[string \"name\"]", source = "name" } - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/modules/cc/strings_spec.lua b/src/test/resources/test-rom/spec/modules/cc/strings_spec.lua deleted file mode 100644 index 900c6fe6f..000000000 --- a/src/test/resources/test-rom/spec/modules/cc/strings_spec.lua +++ /dev/null @@ -1,41 +0,0 @@ -describe("cc.pretty", function() - local str = require("cc.strings") - - describe("wrap", function() - it("validates arguments", function() - str.wrap("test string is long") - str.wrap("test string is long", 11) - expect.error(str.wrap, nil):eq("bad argument #1 (expected string, got nil)") - expect.error(str.wrap, "", false):eq("bad argument #2 (expected number, got boolean)") - end) - - it("wraps lines", function() - expect(str.wrap("test string is long")[1]):eq("test string is long") - - expect(str.wrap("test string is long", 15)[1]):eq("test string is ") - expect(str.wrap("test string is long", 15)[2]):eq("long") - - expect(str.wrap("test string is long", 12)[1]):eq("test string ") - expect(str.wrap("test string is long", 12)[2]):eq("is long") - - expect(str.wrap("test string is long", 11)[1]):eq("test string") - expect(str.wrap("test string is long", 11)[2]):eq("is long") - end) - end) - - describe("ensure_width", function() - it("validates arguments", function() - str.wrap("test string is long") - str.wrap("test string is long", 11) - expect.error(str.ensure_width, nil):eq("bad argument #1 (expected string, got nil)") - expect.error(str.ensure_width, "", false):eq("bad argument #2 (expected number, got boolean)") - end) - - it("pads lines", function() - expect(str.ensure_width("test string is long", 25)):eq("test string is long ") - end) - it("truncates lines", function() - expect(str.ensure_width("test string is long", 15)):eq("test string is ") - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/programs/advanced/multishell_spec.lua b/src/test/resources/test-rom/spec/programs/advanced/multishell_spec.lua deleted file mode 100644 index d0917c296..000000000 --- a/src/test/resources/test-rom/spec/programs/advanced/multishell_spec.lua +++ /dev/null @@ -1,30 +0,0 @@ -describe("The multishell program", function() - describe("multishell.setFocus", function() - it("validates arguments", function() - multishell.setFocus(multishell.getFocus()) - expect.error(multishell.setFocus, nil):eq("bad argument #1 (expected number, got nil)") - end) - end) - - describe("multishell.getTitle", function() - it("validates arguments", function() - multishell.getTitle(1) - expect.error(multishell.getTitle, nil):eq("bad argument #1 (expected number, got nil)") - end) - end) - - describe("multishell.setTitle", function() - it("validates arguments", function() - multishell.setTitle(1, multishell.getTitle(1)) - expect.error(multishell.setTitle, nil):eq("bad argument #1 (expected number, got nil)") - expect.error(multishell.setTitle, 1, nil):eq("bad argument #2 (expected string, got nil)") - end) - end) - - describe("multishell.launch", function() - it("validates arguments", function() - expect.error(multishell.launch, nil):eq("bad argument #1 (expected table, got nil)") - expect.error(multishell.launch, _ENV, nil):eq("bad argument #2 (expected string, got nil)") - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/programs/command/exec_spec.lua b/src/test/resources/test-rom/spec/programs/command/exec_spec.lua deleted file mode 100644 index 4e6b37b2c..000000000 --- a/src/test/resources/test-rom/spec/programs/command/exec_spec.lua +++ /dev/null @@ -1,33 +0,0 @@ -local capture = require "test_helpers".capture_program - -describe("The exec program", function() - it("displays an error without the commands api", function() - stub(_G, "commands", nil) - expect(capture(stub, "/rom/programs/command/exec.lua")) - :matches { ok = true, output = "", error = "Requires a Command Computer.\n" } - end) - - it("displays its usage when given no argument", function() - stub(_G, "commands", {}) - expect(capture(stub, "/rom/programs/command/exec.lua")) - :matches { ok = true, output = "", error = "Usage: /rom/programs/command/exec.lua \n" } - end) - - it("runs a command", function() - stub(_G, "commands", { - exec = function() return true, { "Hello World!" } end, - }) - - expect(capture(stub, "/rom/programs/command/exec.lua computercraft")) - :matches { ok = true, output = "Success\nHello World!\n", error = "" } - end) - - it("reports command failures", function() - stub(_G, "commands", { - exec = function() return false, { "Hello World!" } end, - }) - - expect(capture(stub, "/rom/programs/command/exec.lua computercraft")) - :matches { ok = true, output = "Hello World!\n", error = "Failed\n" } - end) -end) diff --git a/src/test/resources/test-rom/spec/programs/copy_spec.lua b/src/test/resources/test-rom/spec/programs/copy_spec.lua deleted file mode 100644 index c18dd54c6..000000000 --- a/src/test/resources/test-rom/spec/programs/copy_spec.lua +++ /dev/null @@ -1,40 +0,0 @@ -local capture = require "test_helpers".capture_program - -describe("The copy program", function() - local function touch(file) - io.open(file, "w"):close() - end - - it("copies a file", function() - touch("/test-files/copy/a.txt") - - shell.run("copy /test-files/copy/a.txt /test-files/copy/b.txt") - - expect(fs.exists("/test-files/copy/a.txt")):eq(true) - expect(fs.exists("/test-files/copy/b.txt")):eq(true) - end) - - it("fails when copying a non-existent file", function() - expect(capture(stub, "copy nothing destination")) - :matches { ok = true, output = "", error = "No matching files\n" } - end) - - it("fails when overwriting an existing file", function() - touch("/test-files/copy/c.txt") - - expect(capture(stub, "copy /test-files/copy/c.txt /test-files/copy/c.txt")) - :matches { ok = true, output = "", error = "Destination exists\n" } - end) - - it("fails when copying into read-only locations", function() - touch("/test-files/copy/d.txt") - - expect(capture(stub, "copy /test-files/copy/d.txt /rom/test.txt")) - :matches { ok = true, output = "", error = "Destination is read-only\n" } - end) - - it("displays the usage when given no arguments", function() - expect(capture(stub, "copy")) - :matches { ok = true, output = "Usage: copy \n", error = "" } - end) -end) diff --git a/src/test/resources/test-rom/spec/programs/delete_spec.lua b/src/test/resources/test-rom/spec/programs/delete_spec.lua deleted file mode 100644 index bf2433467..000000000 --- a/src/test/resources/test-rom/spec/programs/delete_spec.lua +++ /dev/null @@ -1,35 +0,0 @@ -describe("The rm program", function() - local function touch(file) - io.open(file, "w"):close() - end - - it("deletes one file", function() - touch("/test-files/a.txt") - - shell.run("rm /test-files/a.txt") - - expect(fs.exists("/test-files/a.txt")):eq(false) - end) - - it("deletes many files", function() - touch("/test-files/a.txt") - touch("/test-files/b.txt") - touch("/test-files/c.txt") - - shell.run("rm /test-files/a.txt /test-files/b.txt") - - expect(fs.exists("/test-files/a.txt")):eq(false) - expect(fs.exists("/test-files/b.txt")):eq(false) - expect(fs.exists("/test-files/c.txt")):eq(true) - end) - - it("deletes a glob", function() - touch("/test-files/a.txt") - touch("/test-files/b.txt") - - shell.run("rm /test-files/*.txt") - - expect(fs.exists("/test-files/a.txt")):eq(false) - expect(fs.exists("/test-files/b.txt")):eq(false) - end) -end) diff --git a/src/test/resources/test-rom/spec/programs/mkdir_spec.lua b/src/test/resources/test-rom/spec/programs/mkdir_spec.lua deleted file mode 100644 index 91dcaf437..000000000 --- a/src/test/resources/test-rom/spec/programs/mkdir_spec.lua +++ /dev/null @@ -1,29 +0,0 @@ -describe("The mkdir program", function() - it("creates a directory", function() - fs.delete("/test-files") - - shell.run("mkdir /test-files/a") - - expect(fs.isDir("/test-files/a")):eq(true) - end) - - it("creates many directories", function() - fs.delete("/test-files") - - shell.run("mkdir /test-files/a /test-files/b") - - expect(fs.isDir("/test-files/a")):eq(true) - expect(fs.isDir("/test-files/b")):eq(true) - end) - - it("can be completed", function() - fs.delete("/test-files") - fs.makeDir("/test-files/a") - fs.makeDir("/test-files/b") - io.open("/test-files.a.txt", "w"):close() - - local complete = shell.getCompletionInfo()["rom/programs/mkdir.lua"].fnComplete - expect(complete(shell, 1, "/test-files/", {})):same { "a/", "b/" } - expect(complete(shell, 2, "/test-files/", { "/" })):same { "a/", "b/" } - end) -end) diff --git a/src/test/resources/test-rom/spec/programs/motd_spec.lua b/src/test/resources/test-rom/spec/programs/motd_spec.lua deleted file mode 100644 index d426fb6e7..000000000 --- a/src/test/resources/test-rom/spec/programs/motd_spec.lua +++ /dev/null @@ -1,36 +0,0 @@ -local capture = require "test_helpers".capture_program - -describe("The motd program", function() - local function setup_date(month, day) - stub(os, "date", function() return { month = month, day = day } end) - end - - it("displays MOTD", function() - setup_date(0, 0) - local file = fs.open("/motd_check.txt", "w") - file.write("Hello World!") - file.close() - settings.set("motd.path", "/motd_check.txt") - - expect(capture(stub, "motd")) - :matches { ok = true, output = "Hello World!\n", error = "" } - end) - - it("displays date-specific MOTD (1/1)", function() - setup_date(1, 1) - expect(capture(stub, "motd")) - :matches { ok = true, output = "Happy new year!\n", error = "" } - end) - - it("displays date-specific MOTD (10/31)", function() - setup_date(10, 31) - expect(capture(stub, "motd")) - :matches { ok = true, output = "OOoooOOOoooo! Spooky!\n", error = "" } - end) - - it("displays date-specific MOTD (12/24)", function() - setup_date(12, 24) - expect(capture(stub, "motd")) - :matches { ok = true, output = "Merry X-mas!\n", error = "" } - end) -end) diff --git a/src/test/resources/test-rom/spec/programs/move_spec.lua b/src/test/resources/test-rom/spec/programs/move_spec.lua deleted file mode 100644 index 7fa8a3857..000000000 --- a/src/test/resources/test-rom/spec/programs/move_spec.lua +++ /dev/null @@ -1,74 +0,0 @@ -local capture = require "test_helpers".capture_program - -describe("The move program", function() - local function cleanup() fs.delete("/test-files/move") end - local function touch(file) - io.open(file, "w"):close() - end - - it("move a file", function() - cleanup() - touch("/test-files/move/a.txt") - - shell.run("move /test-files/move/a.txt /test-files/move/b.txt") - - expect(fs.exists("/test-files/move/a.txt")):eq(false) - expect(fs.exists("/test-files/move/b.txt")):eq(true) - end) - - it("moves a file to a directory", function() - cleanup() - touch("/test-files/move/a.txt") - fs.makeDir("/test-files/move/a") - - expect(capture(stub, "move /test-files/move/a.txt /test-files/move/a")) - :matches { ok = true } - - expect(fs.exists("/test-files/move/a.txt")):eq(false) - expect(fs.exists("/test-files/move/a/a.txt")):eq(true) - end) - - it("fails when moving a file which doesn't exist", function() - expect(capture(stub, "move nothing destination")) - :matches { ok = true, output = "", error = "No matching files\n" } - end) - - it("fails when overwriting an existing file", function() - cleanup() - touch("/test-files/move/a.txt") - - expect(capture(stub, "move /test-files/move/a.txt /test-files/move/a.txt")) - :matches { ok = true, output = "", error = "Destination exists\n" } - end) - - it("fails when moving to read-only locations", function() - cleanup() - touch("/test-files/move/a.txt") - - expect(capture(stub, "move /test-files/move/a.txt /rom/test.txt")) - :matches { ok = true, output = "", error = "Destination is read-only\n" } - end) - - it("fails when moving from read-only locations", function() - expect(capture(stub, "move /rom/startup.lua /test-files/move/not-exist.txt")) - :matches { ok = true, output = "", error = "Cannot move read-only file /rom/startup.lua\n" } - end) - - it("fails when moving mounts", function() - expect(capture(stub, "move /rom /test-files/move/rom")) - :matches { ok = true, output = "", error = "Cannot move mount /rom\n" } - end) - - it("fails when moving a file multiple times", function() - cleanup() - touch("/test-files/move/a.txt") - touch("/test-files/move/b.txt") - expect(capture(stub, "move /test-files/move/*.txt /test-files/move/c.txt")) - :matches { ok = true, output = "", error = "Cannot overwrite file multiple times\n" } - end) - - it("displays the usage with no arguments", function() - expect(capture(stub, "move")) - :matches { ok = true, output = "Usage: move \n", error = "" } - end) -end) diff --git a/src/test/resources/test-rom/spec/programs/shell_spec.lua b/src/test/resources/test-rom/spec/programs/shell_spec.lua deleted file mode 100644 index 9b9dc7188..000000000 --- a/src/test/resources/test-rom/spec/programs/shell_spec.lua +++ /dev/null @@ -1,94 +0,0 @@ -describe("The shell", function() - describe("require", function() - it("validates arguments", function() - require("math") - expect.error(require, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("shell.run", function() - it("sets the arguments", function() - local handle = fs.open("test-files/out.txt", "w") - handle.writeLine("_G.__arg = arg") - handle.close() - - shell.run("/test-files/out.txt", "arg1", "arg2") - fs.delete("test-files/out.txt") - - local args = _G.__arg - _G.__arg = nil - - expect(args):same { [0] = "/test-files/out.txt", "arg1", "arg2" } - end) - end) - - describe("shell.setDir", function() - it("validates arguments", function() - shell.setDir(shell.dir()) - expect.error(shell.setDir, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("shell.setPath", function() - it("validates arguments", function() - shell.setPath(shell.path()) - expect.error(shell.setPath, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("shell.resolve", function() - it("validates arguments", function() - shell.resolve("") - expect.error(shell.resolve, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("shell.resolveProgram", function() - it("validates arguments", function() - shell.resolveProgram("ls") - expect.error(shell.resolveProgram, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("shell.complete", function() - it("validates arguments", function() - shell.complete("ls") - expect.error(shell.complete, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("shell.setCompletionFunction", function() - it("validates arguments", function() - expect.error(shell.setCompletionFunction, nil):eq("bad argument #1 (expected string, got nil)") - expect.error(shell.setCompletionFunction, "", nil):eq("bad argument #2 (expected function, got nil)") - end) - end) - - describe("shell.setCompletionFunction", function() - it("validates arguments", function() - expect.error(shell.setCompletionFunction, nil):eq("bad argument #1 (expected string, got nil)") - expect.error(shell.setCompletionFunction, "", nil):eq("bad argument #2 (expected function, got nil)") - end) - end) - - describe("shell.setAlias", function() - it("validates arguments", function() - shell.setAlias("sl", "ls") - expect.error(shell.setAlias, nil):eq("bad argument #1 (expected string, got nil)") - expect.error(shell.setAlias, "", nil):eq("bad argument #2 (expected string, got nil)") - end) - end) - - describe("shell.clearAlias", function() - it("validates arguments", function() - shell.clearAlias("sl") - expect.error(shell.clearAlias, nil):eq("bad argument #1 (expected string, got nil)") - end) - end) - - describe("shell.switchTab", function() - it("validates arguments", function() - expect.error(shell.switchTab, nil):eq("bad argument #1 (expected number, got nil)") - end) - end) -end) diff --git a/src/test/resources/test-rom/spec/programs/turtle/craft_spec.lua b/src/test/resources/test-rom/spec/programs/turtle/craft_spec.lua deleted file mode 100644 index 95b953b38..000000000 --- a/src/test/resources/test-rom/spec/programs/turtle/craft_spec.lua +++ /dev/null @@ -1,69 +0,0 @@ -local capture = require "test_helpers".capture_program - -describe("The craft program", function() - it("errors when not a turtle", function() - stub(_G, "turtle", nil) - - expect(capture(stub, "/rom/programs/turtle/craft.lua")) - :matches { ok = true, output = "", error = "Requires a Turtle\n" } - end) - - it("fails when turtle.craft() is unavailable", function() - stub(_G, "turtle", {}) - - expect(capture(stub, "/rom/programs/turtle/craft.lua")) - :matches { ok = true, output = "Requires a Crafty Turtle\n", error = "" } - end) - - it("displays its usage when given no arguments", function() - stub(_G, "turtle", { craft = function() end }) - - expect(capture(stub, "/rom/programs/turtle/craft.lua")) - :matches { ok = true, output = "Usage: /rom/programs/turtle/craft.lua [number]\n", error = "" } - end) - - it("crafts multiple items", function() - local item_count = 3 - stub(_G, "turtle", { - craft = function() - item_count = 1 - return true - end, - getItemCount = function() return item_count end, - getSelectedSlot = function() return 1 end, - }) - - expect(capture(stub, "/rom/programs/turtle/craft.lua 2")) - :matches { ok = true, output = "2 items crafted\n", error = "" } - end) - - it("craft a single item", function() - local item_count = 2 - stub(_G, "turtle", { - craft = function() - item_count = 1 - return true - end, - getItemCount = function() return item_count end, - getSelectedSlot = function() return 1 end, - }) - - expect(capture(stub, "/rom/programs/turtle/craft.lua 1")) - :matches { ok = true, output = "1 item crafted\n", error = "" } - end) - - it("crafts no items", function() - local item_count = 2 - stub(_G, "turtle", { - craft = function() - item_count = 1 - return false - end, - getItemCount = function() return item_count end, - getSelectedSlot = function() return 1 end, - }) - - expect(capture(stub, "/rom/programs/turtle/craft.lua 1")) - :matches { ok = true, output = "No items crafted\n", error = "" } - end) -end) diff --git a/src/test/resources/test-rom/spec/programs/turtle/equip_spec.lua b/src/test/resources/test-rom/spec/programs/turtle/equip_spec.lua deleted file mode 100644 index cc12aa367..000000000 --- a/src/test/resources/test-rom/spec/programs/turtle/equip_spec.lua +++ /dev/null @@ -1,89 +0,0 @@ -local capture = require "test_helpers".capture_program - -describe("The turtle equip program", function() - it("errors when not a turtle", function() - stub(_G, "turtle", nil) - - expect(capture(stub, "/rom/programs/turtle/equip.lua")) - :matches { ok = true, output = "", error = "Requires a Turtle\n" } - end) - - - it("displays its usage when given no arguments", function() - stub(_G, "turtle", {}) - - expect(capture(stub, "/rom/programs/turtle/equip.lua")) - :matches { ok = true, output = "Usage: /rom/programs/turtle/equip.lua \n", error = "" } - end) - - it("equip nothing", function() - stub(_G, "turtle", { - select = function() end, - getItemCount = function() return 0 end, - }) - - expect(capture(stub, "/rom/programs/turtle/equip.lua 1 left")) - :matches { ok = true, output = "Nothing to equip\n", error = "" } - expect(capture(stub, "/rom/programs/turtle/equip.lua 1 right")) - :matches { ok = true, output = "Nothing to equip\n", error = "" } - end) - - it("swaps existing upgrades", function() - stub(_G, "turtle", { - select = function() end, - getItemCount = function() return 1 end, - equipLeft = function() return true end, - equipRight = function() return true end, - }) - - expect(capture(stub, "/rom/programs/turtle/equip.lua 1 left")) - :matches { ok = true, output = "Items swapped\n", error = "" } - expect(capture(stub, "/rom/programs/turtle/equip.lua 1 right")) - :matches { ok = true, output = "Items swapped\n", error = "" } - end) - - describe("equips a new upgrade", function() - local function setup() - local item_count = 1 - stub(_G, "turtle", { - select = function() end, - getItemCount = function() return item_count end, - equipLeft = function() - item_count = 0 - return true - end, - equipRight = function() - item_count = 0 - return true - end, - }) - end - - it("on the left", function() - setup() - expect(capture(stub, "/rom/programs/turtle/equip.lua 1 left")) - :matches { ok = true, output = "Item equipped\n", error = "" } - end) - - it("on the right", function() - setup() - expect(capture(stub, "/rom/programs/turtle/equip.lua 1 right")) - :matches { ok = true, output = "Item equipped\n", error = "" } - end) - end) - - it("handles when an upgrade cannot be equipped", function() - stub(_G, "turtle", { - select = function() end, - getItemCount = function() return 1 end, - equipLeft = function() return false end, - equipRight = function() return false end, - }) - - expect(capture(stub, "/rom/programs/turtle/equip.lua 1 left")) - :matches { ok = true, output = "Item not equippable\n", error = "" } - expect(capture(stub, "/rom/programs/turtle/equip.lua 1 right")) - :matches { ok = true, output = "Item not equippable\n", error = "" } - end) - -end) diff --git a/src/test/resources/test-rom/spec/programs/turtle/refuel_spec.lua b/src/test/resources/test-rom/spec/programs/turtle/refuel_spec.lua deleted file mode 100644 index 5ba397b72..000000000 --- a/src/test/resources/test-rom/spec/programs/turtle/refuel_spec.lua +++ /dev/null @@ -1,62 +0,0 @@ -local capture = require "test_helpers".capture_program - -describe("The refuel program", function() - local function setup_turtle(fuel_level, fuel_limit, item_count) - stub(_G, "turtle", { - getFuelLevel = function() - return fuel_level - end, - getItemCount = function() - return item_count - end, - refuel = function(nLimit) - item_count = item_count - nLimit - fuel_level = fuel_level + nLimit - end, - select = function() - end, - getFuelLimit = function() - return fuel_limit - end, - }) - end - - it("errors when not a turtle", function() - stub(_G, "turtle", nil) - - expect(capture(stub, "/rom/programs/turtle/refuel.lua")) - :matches { ok = true, output = "", error = "Requires a Turtle\n" } - end) - - - it("displays its usage when given too many argument", function() - setup_turtle(0, 5, 0) - expect(capture(stub, "/rom/programs/turtle/refuel.lua a b")) - :matches { ok = true, output = "Usage: /rom/programs/turtle/refuel.lua [number]\n", error = "" } - end) - - it("requires a numeric argument", function() - setup_turtle(0, 0, 0) - expect(capture(stub, "/rom/programs/turtle/refuel.lua nothing")) - :matches { ok = true, output = "Invalid limit, expected a number or \"all\"\n", error = "" } - end) - - it("refuels the turtle", function() - setup_turtle(0, 10, 5) - - expect(capture(stub, "/rom/programs/turtle/refuel.lua 5")) - :matches { ok = true, output = "Fuel level is 5\n", error = "" } - end) - - it("reports when the fuel limit is reached", function() - setup_turtle(0, 5, 5) - expect(capture(stub, "/rom/programs/turtle/refuel.lua 5")) - :matches { ok = true, output = "Fuel level is 5\nFuel limit reached\n", error = "" } - end) - - it("reports when the fuel level is unlimited", function() - setup_turtle("unlimited", 5, 5) - expect(capture(stub, "/rom/programs/turtle/refuel.lua 5")) - :matches { ok = true, output = "Fuel level is unlimited\n", error = "" } - end) -end) diff --git a/src/test/resources/test-rom/spec/programs/turtle/unequip_spec.lua b/src/test/resources/test-rom/spec/programs/turtle/unequip_spec.lua deleted file mode 100644 index 627d5952a..000000000 --- a/src/test/resources/test-rom/spec/programs/turtle/unequip_spec.lua +++ /dev/null @@ -1,69 +0,0 @@ -local capture = require "test_helpers".capture_program - -describe("The turtle unequip program", function() - it("errors when not a turtle", function() - stub(_G, "turtle", nil) - - expect(capture(stub, "/rom/programs/turtle/unequip.lua")) - :matches { ok = true, output = "", error = "Requires a Turtle\n" } - end) - - - it("displays its usage when given no arguments", function() - stub(_G, "turtle", {}) - - expect(capture(stub, "/rom/programs/turtle/unequip.lua")) - :matches { ok = true, output = "Usage: /rom/programs/turtle/unequip.lua \n", error = "" } - end) - - it("says when nothing was unequipped", function() - stub(_G, "turtle", { - select = function() end, - getItemCount = function() return 0 end, - equipRight = function() return true end, - equipLeft = function() return true end, - }) - - expect(capture(stub, "/rom/programs/turtle/unequip.lua left")) - :matches { ok = true, output = "Nothing to unequip\n", error = "" } - expect(capture(stub, "/rom/programs/turtle/unequip.lua right")) - :matches { ok = true, output = "Nothing to unequip\n", error = "" } - end) - - it("unequips a upgrade", function() - local item_count = 0 - stub(_G, "turtle", { - select = function() end, - getItemCount = function() return item_count end, - equipRight = function() - item_count = 1 - return true - end, - equipLeft = function() - item_count = 1 - return true - end, - }) - - expect(capture(stub, "/rom/programs/turtle/unequip.lua left")) - :matches { ok = true, output = "Item unequipped\n", error = "" } - item_count = 0 - expect(capture(stub, "/rom/programs/turtle/unequip.lua right")) - :matches { ok = true, output = "Item unequipped\n", error = "" } - end) - - it("fails when the turtle is full", function() - stub(_G, "turtle", { - select = function() end, - getItemCount = function() return 1 end, - equipRight = function() return true end, - equipLeft = function() return true end, - }) - - expect(capture(stub, "/rom/programs/turtle/unequip.lua left")) - :matches { ok = true, output = "No space to unequip item\n", error = "" } - expect(capture(stub, "/rom/programs/turtle/unequip.lua right")) - :matches { ok = true, output = "No space to unequip item\n", error = "" } - end) - -end)