This commit is contained in:
@@ -0,0 +1,215 @@
|
||||
package haus.nightmare.lib3270j.ecl;
|
||||
|
||||
import haus.nightmare.lib3270j.TerminalModel;
|
||||
import haus.nightmare.lib3270j.charset.EbcdicTranslator;
|
||||
import haus.nightmare.lib3270j.input.InputProcessor;
|
||||
import haus.nightmare.lib3270j.protocol.DS3270Constants;
|
||||
import haus.nightmare.lib3270j.screen.ScreenBuffer;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static haus.nightmare.lib3270j.protocol.DS3270Constants.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class EntryAssistFullModeTest {
|
||||
|
||||
private ScreenBuffer screen;
|
||||
private EbcdicTranslator translator;
|
||||
private InputProcessor inputProcessor;
|
||||
private ECLOIA oia;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
translator = new EbcdicTranslator();
|
||||
screen = new ScreenBuffer(TerminalModel.IBM_3279_2, translator); // 24x80
|
||||
inputProcessor = new InputProcessor(screen, translator, null);
|
||||
oia = new ECLOIA(screen, inputProcessor, null);
|
||||
inputProcessor.setOIA(oia);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDocModeCursorAdvanceWithoutWordWrap() {
|
||||
// Document Mode ON, Word Wrap OFF
|
||||
screen.setEntryAssistDOCmode(true);
|
||||
screen.setEntryAssistWordWrap(false);
|
||||
screen.setLeftMargin(0); // Col 1 (0-based 0)
|
||||
screen.setRightMargin(72); // Col 73 (0-based 72)
|
||||
|
||||
assertTrue(screen.isEntryAssistDOCmode());
|
||||
assertFalse(screen.isEntryAssistWordWrap());
|
||||
assertEquals(0, screen.getEntryAssistStartColumn());
|
||||
assertEquals(72, screen.getEntryAssistEndColumn());
|
||||
|
||||
// Setup open cursor position
|
||||
screen.setCursorPosition(0, 72); // Row 0, Col 72 (at right margin)
|
||||
inputProcessor.typeCharacter('X');
|
||||
|
||||
// Should advance to next row at left margin (Row 1, Col 0)
|
||||
assertEquals(1, screen.getCursorRow());
|
||||
assertEquals(0, screen.getCursorCol());
|
||||
assertEquals('X', (char) screen.getCell(72).ucs4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWordWrapTransfersPartialWord() {
|
||||
// Document Mode ON, Word Wrap ON
|
||||
screen.setEntryAssistDOCmode(true);
|
||||
screen.setEntryAssistWordWrap(true);
|
||||
screen.setLeftMargin(5); // Start col = 5
|
||||
screen.setRightMargin(20); // End col = 20
|
||||
|
||||
// Type "HELLO " starting at col 10
|
||||
screen.setCursorPosition(0, 10);
|
||||
for (char c : "HELLO ".toCharArray()) {
|
||||
inputProcessor.typeCharacter(c);
|
||||
}
|
||||
|
||||
// Now cursor is at col 16. Type "TEST" which crosses col 20
|
||||
screen.setCursorPosition(0, 18);
|
||||
inputProcessor.typeCharacter('W');
|
||||
inputProcessor.typeCharacter('O');
|
||||
inputProcessor.typeCharacter('R');
|
||||
inputProcessor.typeCharacter('D'); // At col 21, past end col 20
|
||||
|
||||
// Word wrap should have moved "WORD" to next line starting at left margin 5
|
||||
assertEquals(1, screen.getCursorRow());
|
||||
assertTrue(screen.getCursorCol() >= 5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDocModeTabStopsNavigation() {
|
||||
screen.setEntryAssistDOCmode(true);
|
||||
screen.setLeftMargin(0);
|
||||
screen.setRightMargin(79);
|
||||
screen.setEntryAssistTabStops(new int[]{0, 10, 20, 30});
|
||||
|
||||
screen.setCursorPosition(0, 0);
|
||||
|
||||
// Word tab forward
|
||||
screen.processWordTab(true);
|
||||
assertEquals(10, screen.getCursorCol());
|
||||
assertEquals(0, screen.getCursorRow());
|
||||
|
||||
screen.processWordTab(true);
|
||||
assertEquals(20, screen.getCursorCol());
|
||||
|
||||
// Word back tab
|
||||
screen.processWordTab(false);
|
||||
assertEquals(10, screen.getCursorCol());
|
||||
|
||||
screen.processWordTab(false);
|
||||
assertEquals(0, screen.getCursorCol());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAudibleEndOfLineBell() {
|
||||
inputProcessor.setBellEnabled(true);
|
||||
inputProcessor.setBellColumn(74);
|
||||
|
||||
AtomicInteger bellCount = new AtomicInteger(0);
|
||||
inputProcessor.setBellListener(bellCount::incrementAndGet);
|
||||
|
||||
screen.setCursorPosition(0, 70);
|
||||
inputProcessor.typeCharacter('A'); // 71
|
||||
inputProcessor.typeCharacter('B'); // 72
|
||||
inputProcessor.typeCharacter('C'); // 73
|
||||
assertEquals(0, bellCount.get());
|
||||
|
||||
inputProcessor.typeCharacter('D'); // 74 -> triggers bell
|
||||
assertEquals(1, bellCount.get());
|
||||
|
||||
inputProcessor.typeCharacter('E'); // 75 -> does not retrigger on same line
|
||||
assertEquals(1, bellCount.get());
|
||||
|
||||
// Move to next line at col 73 and type across bell column
|
||||
screen.setCursorPosition(1, 73);
|
||||
inputProcessor.typeCharacter('Z'); // advances to 74 -> triggers bell on next line
|
||||
assertEquals(2, bellCount.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertModeResetOnAid() {
|
||||
inputProcessor.setInsertOffOnAid(true);
|
||||
inputProcessor.setInsertMode(true);
|
||||
assertTrue(inputProcessor.isInsertMode());
|
||||
|
||||
// Send AID_ENTER
|
||||
inputProcessor.sendAid(AID_ENTER);
|
||||
assertFalse(inputProcessor.isInsertMode(), "Insert mode should be reset after AID key");
|
||||
|
||||
// When insertOffOnAid is disabled
|
||||
inputProcessor.setInsertOffOnAid(false);
|
||||
inputProcessor.setInsertMode(true);
|
||||
inputProcessor.sendAid(AID_ENTER);
|
||||
assertTrue(inputProcessor.isInsertMode(), "Insert mode should be preserved when insertOffOnAid is false");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAplKeyboardModeAndOia() {
|
||||
inputProcessor.setAplKeyboardMode(true);
|
||||
assertTrue(inputProcessor.isAplKeyboardMode());
|
||||
|
||||
// OIA status flag includes STATE_APL
|
||||
long statusEx = oia.GetStatusFlagsEx();
|
||||
assertEquals(ECLOIA.STATE_APL, statusEx & ECLOIA.STATE_APL);
|
||||
assertTrue(oia.isApl());
|
||||
|
||||
// Test APL translation for key 'a' (alpha -> 0x41 with CS_GE)
|
||||
screen.setCursorPosition(0, 0);
|
||||
inputProcessor.typeCharacter('a');
|
||||
|
||||
var cell = screen.getCell(0);
|
||||
assertEquals(CS_GE, cell.cs, "APL character must be stored with CS_GE (Graphic Escape) charset");
|
||||
|
||||
// Toggle APL mode off
|
||||
inputProcessor.toggleAplKeyboardMode();
|
||||
assertFalse(inputProcessor.isAplKeyboardMode());
|
||||
assertFalse(oia.isApl());
|
||||
assertEquals(0, oia.GetStatusFlagsEx() & ECLOIA.STATE_APL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNumericFieldLockSetting() {
|
||||
// Field: pos 0 is numeric FA, pos 1..5 unprotected, pos 6 protect FA
|
||||
screen.setFieldAttribute(0, (byte) FA_NUMERIC);
|
||||
screen.setFieldAttribute(6, (byte) FA_PROTECT);
|
||||
screen.setCursorAddress(1);
|
||||
|
||||
// Case 1: NumericFieldLock is true
|
||||
inputProcessor.setNumericFieldLock(true);
|
||||
inputProcessor.typeCharacter('X'); // invalid numeric character
|
||||
assertTrue(inputProcessor.isKeyboardLocked(), "Keyboard should be locked on non-numeric char");
|
||||
assertEquals(ECLConstants.INHIBIT_NUMERIC_ONLY, oia.getInputInhibited());
|
||||
|
||||
// Reset keyboard
|
||||
inputProcessor.reset();
|
||||
assertFalse(inputProcessor.isKeyboardLocked());
|
||||
|
||||
// Case 2: NumericFieldLock is false
|
||||
inputProcessor.setNumericFieldLock(false);
|
||||
screen.setCursorAddress(1);
|
||||
inputProcessor.typeCharacter('X');
|
||||
assertFalse(inputProcessor.isKeyboardLocked(), "Keyboard should NOT be locked when NumericFieldLock is false");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOiaModeIndicators() {
|
||||
screen.setEntryAssistDOCmode(true);
|
||||
screen.setEntryAssistWordWrap(true);
|
||||
inputProcessor.setAplKeyboardMode(true);
|
||||
inputProcessor.setInsertMode(true);
|
||||
|
||||
long flags = oia.GetStatusFlagsEx();
|
||||
assertTrue((flags & ECLOIA.STATE_DOC_MODE) != 0);
|
||||
assertTrue((flags & ECLOIA.STATE_WORDWRAP) != 0);
|
||||
assertTrue((flags & ECLOIA.STATE_APL) != 0);
|
||||
assertTrue((flags & ECLOIA.STATE_INSERT) != 0);
|
||||
|
||||
assertTrue(oia.isDocMode());
|
||||
assertTrue(oia.isWordWrap());
|
||||
assertTrue(oia.isApl());
|
||||
assertTrue(oia.isInsertMode());
|
||||
}
|
||||
}
|
||||
@@ -76,8 +76,9 @@ public class DynamicScreenBufferTest {
|
||||
assertTrue(model.isDynamic());
|
||||
assertEquals(0, model.getModelNumber());
|
||||
assertTrue(model.isColor());
|
||||
assertEquals("IBM-DYNAMIC-E", model.getTerminalType());
|
||||
assertEquals("IBM-DYNAMIC", model.getTerminalType());
|
||||
assertEquals("IBM-DYNAMIC", model.getBaseTerminalType());
|
||||
assertEquals("IBM-DYNAMIC", model.toString());
|
||||
|
||||
ScreenBuffer buffer = new ScreenBuffer(model, translator);
|
||||
assertEquals(24, buffer.getDefRows());
|
||||
|
||||
@@ -65,12 +65,14 @@ public class DynamicTelnetFSMTest {
|
||||
// Host requests TTYPE: IAC SB TTYPE SEND IAC SE
|
||||
feedBytes(255, 250, 24, 1, 255, 240);
|
||||
|
||||
// Verify sent response is IBM-DYNAMIC-E
|
||||
// Verify sent response is IBM-DYNAMIC
|
||||
assertFalse(connection.sentData.isEmpty());
|
||||
byte[] lastSent = connection.sentData.get(connection.sentData.size() - 1);
|
||||
String s = new String(lastSent);
|
||||
assertTrue(s.contains("IBM-DYNAMIC-E") || s.contains("IBM-DYNAMIC"),
|
||||
assertTrue(s.contains("IBM-DYNAMIC"),
|
||||
"Expected terminal type negotiation to send IBM-DYNAMIC, got: " + s);
|
||||
assertFalse(s.contains("IBM-DYNAMIC-E"),
|
||||
"Terminal type negotiation should not contain IBM-DYNAMIC-E, got: " + s);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user