Improved test coverage for timed device, applesoft basic editing

This commit is contained in:
Badvision 2024-08-04 11:02:57 -05:00
parent f34ba40ff0
commit 751c66c53f
7 changed files with 200 additions and 14 deletions

View File

@ -123,7 +123,7 @@
</execution>
</executions>
</plugin>
<!-- <plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
@ -158,7 +158,7 @@
<limit>
<counter>COMPLEXITY</counter>
<value>COVEREDRATIO</value>
<minimum>0.60</minimum>
<minimum>0.35</minimum>
</limit>
</limits>
</rule>
@ -166,7 +166,7 @@
</configuration>
</execution>
</executions>
</plugin> -->
</plugin>
</plugins>
</build>

View File

@ -61,6 +61,10 @@ public class Emulator {
if (instance.computer != null) {
instance.computer.getMotherboard().suspend();
instance.computer.getMotherboard().detach();
if (instance.computer.getVideo() != null) {
instance.computer.getVideo().suspend();
instance.computer.getVideo().detach();
}
}
}
instance = null;

View File

@ -211,7 +211,7 @@ public class ApplesoftProgram {
* Move variables around to accommodate bigger program
* @param programEnd Program ending address
*/
private void relocateVariables(int programEnd) {
public void relocateVariables(int programEnd) {
Emulator.withMemory(memory->{
int currentEnd = memory.readWordRaw(END_OF_PROG_POINTER);
memory.writeWord(END_OF_PROG_POINTER, programEnd, false, true);

View File

@ -81,6 +81,7 @@ public abstract class TimedDevice extends Device {
public final void resetSyncTimer() {
nextSync = System.nanoTime() + nanosPerInterval;
waitUntil = null;
cycleTimer = 0;
}
@ -119,9 +120,7 @@ public abstract class TimedDevice extends Device {
public final void setMaxSpeed(boolean enabled) {
maxspeed = enabled;
if (!enabled) {
resetSyncTimer();
}
resetSyncTimer();
}
public final boolean isMaxSpeedEnabled() {
@ -129,7 +128,7 @@ public abstract class TimedDevice extends Device {
}
public final boolean isMaxSpeed() {
return forceMaxspeed || maxspeed;
return forceMaxspeed || maxspeed || tempSpeedDuration > 0;
}
public final long getSpeedInHz() {

View File

@ -1,5 +1,6 @@
package jace;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import javafx.application.Platform;
@ -12,5 +13,11 @@ public abstract class AbstractFXTest {
fxInitialized = true;
Platform.startup(() -> {});
}
}
}
@AfterClass
public static void shutdown() {
Emulator.abort();
Platform.exit();
}
}

View File

@ -2,18 +2,63 @@ package jace.applesoft;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.Collections;
import org.junit.BeforeClass;
import org.junit.Test;
import jace.Emulator;
import jace.TestUtils;
import jace.apple2e.MOS65C02;
import jace.apple2e.RAM128k;
import jace.core.Computer;
import jace.core.SoundMixer;
import jace.ide.Program;
import jace.ide.Program.DocumentType;
public class ApplesoftTest {
static Computer computer;
public static MOS65C02 cpu;
static RAM128k ram;
@BeforeClass
public static void setupClass() {
TestUtils.initComputer();
SoundMixer.MUTE = true;
computer = Emulator.withComputer(c->c, null);
cpu = (MOS65C02) computer.getCpu();
ram = (RAM128k) computer.getMemory();
}
@Test
public void fromStringTest() {
String programSource = "10 PRINT \"Hello, World!\"\n20 PRINT \"Goodbye!\"";
ApplesoftProgram program = ApplesoftProgram.fromString(programSource);
assertNotNull(program);
assertEquals(2, program.lines.size());
Line line1 = program.lines.get(0);
String programSource = "10 PRINT \"Hello, World!\"\n\n20 PRINT \"Goodbye!\"\n";
ApplesoftHandler handler = new ApplesoftHandler();
// We want to test as much as we can but right now it's heavily integrated with the UI
Program program = new Program(DocumentType.applesoft, Collections.emptyMap()) {
String value;
@Override
public String getValue() {
return value;
}
@Override
public void setValue(String value) {
this.value = value;
}
};
program.setValue(programSource);
var compileResult = handler.compile(program);
assertNotNull(compileResult.getCompiledAsset());
assertTrue(compileResult.isSuccessful());
assertTrue(compileResult.getErrors().isEmpty());
assertTrue(compileResult.getWarnings().isEmpty());
assertTrue(compileResult.getOtherMessages().isEmpty());
assertTrue(compileResult.getRawOutput().isEmpty());
assertEquals(2, compileResult.getCompiledAsset().lines.size());
Line line1 = compileResult.getCompiledAsset().lines.get(0);
assertEquals(10, line1.getNumber());
assertEquals(1, line1.getCommands().size());
Command command1 = line1.getCommands().get(0);
@ -23,6 +68,24 @@ public class ApplesoftTest {
match += command1.parts.get(idx).toString();
}
assertEquals("\"Hello, World!\"", match);
// Does nothing but test coverage is test coverage
handler.clean(null);
// Now let's try to execute and see if we can read the program back
handler.execute(compileResult);
ApplesoftProgram program2 = Emulator.withComputer(c->ApplesoftProgram.fromMemory(c.getMemory()), null);
assertEquals(2, program2.getLength());
Line line2 = program2.lines.get(0);
assertEquals(10, line2.getNumber());
assertEquals(1, line2.getCommands().size());
Command command2 = line2.getCommands().get(0);
assertEquals(0xBA, command2.parts.get(0).getByte() & 0x0ff);
match = "";
for (int idx=1; idx < command2.parts.size(); idx++) {
match += command2.parts.get(idx).toString();
}
assertEquals("\"Hello, World!\"", match);
}
@Test
@ -35,4 +98,15 @@ public class ApplesoftTest {
String programSource = program.toString();
assertEquals("10 PRINT \"Hello, world!\"\n20 PRINT \"Goodbye!\"\n", programSource);
}
@Test
public void relocateVariablesTest() {
ApplesoftProgram program = new ApplesoftProgram();
Line line1 = Line.fromString("10 print \"Hello, world!\"");
Line line2 = Line.fromString("20 print \"Goodbye!\"");
program.lines.add(line1);
program.lines.add(line2);
program.relocateVariables(0x6000);
// We need better assertions here but for now we just want to make sure it doesn't crash
}
}

View File

@ -0,0 +1,102 @@
package jace.core;
import org.junit.Before;
import org.junit.Test;
import jace.AbstractFXTest;
import static org.junit.Assert.*;
public class TimedDeviceTest extends AbstractFXTest {
private TimedDevice timedDevice;
public int countedTicks = 0;
@Before
public void setUp() {
countedTicks = 0;
timedDevice = new TimedDevice(true) {
@Override
public String getShortName() {
return "Test";
}
@Override
protected String getDeviceName() {
return "Test";
}
@Override
public void tick() {
countedTicks++;
}
};
}
@Test
public void testSetSpeedInHz() {
long newSpeed = 2000000;
timedDevice.setSpeedInHz(newSpeed);
assertEquals(newSpeed, timedDevice.getSpeedInHz());
}
@Test
public void testSetSpeedInPercentage() {
int ratio = 50;
timedDevice.setSpeedInPercentage(ratio);
assertEquals(ratio, timedDevice.getSpeedRatio());
}
@Test
public void testMaxSpeed() {
// Use temp max speed
timedDevice.setMaxSpeed(false);
timedDevice.enableTempMaxSpeed();
assertTrue("Max speed enabled", timedDevice.isMaxSpeed());
timedDevice.disableTempMaxSpeed();
assertFalse("Max speed disabled", timedDevice.isMaxSpeed());
// Run 250 cycles and make sure none were skipped
timedDevice.setSpeedInHz(1000);
timedDevice.resume();
for (int i=0 ; i<250 ; i++) {
timedDevice.enableTempMaxSpeed();
timedDevice.doTick();
}
assertEquals("250 ticks were counted", 250, countedTicks);
// Disable temp max speed
timedDevice.disableTempMaxSpeed();
countedTicks = 0;
for (int i=0 ; i<250 ; i++) {
timedDevice.doTick();
}
assertTrue("Should have counted fewer than 250 ticks", countedTicks < 250);
// Now use max speed
timedDevice.setMaxSpeed(true);
countedTicks = 0;
for (int i=0 ; i<250 ; i++) {
timedDevice.doTick();
}
assertEquals("250 ticks were counted", 250, countedTicks);
}
@Test
public void testReconfigure() {
timedDevice.reconfigure();
// Add assertions here
}
@Test
public void testTicks() {
timedDevice.setSpeedInHz(1000);
timedDevice.resume();
long now = System.nanoTime();
for (countedTicks=0 ; countedTicks<250 ; ) {
timedDevice.doTick();
}
assertEquals("250 ticks were counted", 250, countedTicks);
long ellapsed = System.nanoTime() - now;
assertTrue("About 250ms elapsed", ellapsed / 1000000 >= 240);
}
}