Fix gradle and add workflows
Build and Test j3270 / Build JAR & Run Tests (push) Failing after 2m24s
Build and Test j3270 / Build JAR & Run Tests (push) Failing after 2m24s
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
package org.lib3270j.charset;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class EbcdicTranslatorTest {
|
||||
|
||||
private final EbcdicTranslator translator = new EbcdicTranslator();
|
||||
|
||||
@Test
|
||||
public void testBasicAlphanumericTranslation() {
|
||||
assertEquals('A', translator.ebcdicToUnicode(0xC1));
|
||||
assertEquals('B', translator.ebcdicToUnicode(0xC2));
|
||||
assertEquals('Z', translator.ebcdicToUnicode(0xE9));
|
||||
assertEquals('a', translator.ebcdicToUnicode(0x81));
|
||||
assertEquals('z', translator.ebcdicToUnicode(0xA9));
|
||||
assertEquals('0', translator.ebcdicToUnicode(0xF0));
|
||||
assertEquals('9', translator.ebcdicToUnicode(0xF9));
|
||||
assertEquals(' ', translator.ebcdicToUnicode(0x40));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReverseTranslation() {
|
||||
assertEquals(0xC1, translator.unicodeToEbcdic('A'));
|
||||
assertEquals(0x81, translator.unicodeToEbcdic('a'));
|
||||
assertEquals(0xF0, translator.unicodeToEbcdic('0'));
|
||||
assertEquals(0x40, translator.unicodeToEbcdic(' '));
|
||||
assertEquals(0x4B, translator.unicodeToEbcdic('.'));
|
||||
assertEquals(0x6B, translator.unicodeToEbcdic(','));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialCharactersCP037() {
|
||||
// [ and ]
|
||||
assertEquals(0xBA, translator.unicodeToEbcdic('['));
|
||||
assertEquals(0xBB, translator.unicodeToEbcdic(']'));
|
||||
assertEquals('[', translator.ebcdicToUnicode(0xBA));
|
||||
assertEquals(']', translator.ebcdicToUnicode(0xBB));
|
||||
|
||||
// { and }
|
||||
assertEquals(0xC0, translator.unicodeToEbcdic('{'));
|
||||
assertEquals(0xD0, translator.unicodeToEbcdic('}'));
|
||||
assertEquals('{', translator.ebcdicToUnicode(0xC0));
|
||||
assertEquals('}', translator.ebcdicToUnicode(0xD0));
|
||||
|
||||
// Backslash \
|
||||
assertEquals(0xE0, translator.unicodeToEbcdic('\\'));
|
||||
assertEquals('\\', translator.ebcdicToUnicode(0xE0));
|
||||
|
||||
// Caret ^
|
||||
assertEquals(0xB0, translator.unicodeToEbcdic('^'));
|
||||
assertEquals('^', translator.ebcdicToUnicode(0xB0));
|
||||
|
||||
// Tilde ~
|
||||
assertEquals(0xA1, translator.unicodeToEbcdic('~'));
|
||||
assertEquals('~', translator.ebcdicToUnicode(0xA1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringRoundTrip() {
|
||||
String test = "Hello World! 123 [TEST] {VAR} \\";
|
||||
byte[] ebcdic = translator.stringToEbcdic(test);
|
||||
String restored = translator.ebcdicToString(ebcdic, 0, ebcdic.length);
|
||||
assertEquals(test, restored);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package org.lib3270j.datastream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lib3270j.TerminalModel;
|
||||
import org.lib3270j.charset.EbcdicTranslator;
|
||||
import org.lib3270j.screen.ScreenBuffer;
|
||||
import org.lib3270j.screen.ExtendedAttribute;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.lib3270j.protocol.DS3270Constants.*;
|
||||
|
||||
public class DataStreamProcessorTest {
|
||||
|
||||
private final EbcdicTranslator translator = new EbcdicTranslator();
|
||||
private final ScreenBuffer screen = new ScreenBuffer(TerminalModel.IBM_3279_4, translator);
|
||||
private final DataStreamProcessor processor = new DataStreamProcessor(screen, translator);
|
||||
|
||||
@Test
|
||||
public void testEraseWriteAndSBAOrder() {
|
||||
// Build an EW record:
|
||||
// Byte 0: CMD_EW (0x05)
|
||||
// Byte 1: WCC (0xC3) - restore keyboard, reset MDT
|
||||
// Byte 2: ORDER_SBA (0x11)
|
||||
// Byte 3, 4: Encoded address for 0 (0x40, 0x40)
|
||||
// Byte 5: ORDER_SF (0x1D)
|
||||
// Byte 6: FA (0xC0) - unprotected
|
||||
// Byte 7..11: EBCDIC "HELLO" (0xC8, 0xC5, 0xD3, 0xD3, 0xD6)
|
||||
byte[] record = new byte[] {
|
||||
(byte) CMD_EW,
|
||||
(byte) 0xC3,
|
||||
(byte) ORDER_SBA,
|
||||
(byte) 0x40, (byte) 0x40,
|
||||
(byte) ORDER_SF,
|
||||
(byte) FA_PRINTABLE,
|
||||
(byte) 0xC8, (byte) 0xC5, (byte) 0xD3, (byte) 0xD3, (byte) 0xD6
|
||||
};
|
||||
|
||||
processor.processRecord(record, 0, record.length, true);
|
||||
|
||||
assertTrue(screen.isFormatted());
|
||||
assertTrue(screen.getCell(0).isFieldAttribute());
|
||||
|
||||
// Positions 1..5 should contain "HELLO"
|
||||
assertEquals('H', screen.getCell(1).ucs4);
|
||||
assertEquals('E', screen.getCell(2).ucs4);
|
||||
assertEquals('L', screen.getCell(3).ucs4);
|
||||
assertEquals('L', screen.getCell(4).ucs4);
|
||||
assertEquals('O', screen.getCell(5).ucs4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRepeatToAddressOrder() {
|
||||
// Write record with RA from 0 to 10 with character 'A' (0xC1)
|
||||
byte[] record = new byte[] {
|
||||
(byte) CMD_EW,
|
||||
(byte) 0xC3,
|
||||
(byte) ORDER_SBA,
|
||||
(byte) 0x40, (byte) 0x40, // Address 0
|
||||
(byte) ORDER_RA,
|
||||
(byte) 0x40, (byte) 0x4A, // Address 10 (0x40, 0x4A)
|
||||
(byte) 0xC1 // EBCDIC 'A'
|
||||
};
|
||||
|
||||
processor.processRecord(record, 0, record.length, true);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
assertEquals('A', screen.getCell(i).ucs4, "Cell " + i + " should be 'A'");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.lib3270j.datastream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lib3270j.TerminalModel;
|
||||
import org.lib3270j.charset.EbcdicTranslator;
|
||||
import org.lib3270j.screen.ScreenBuffer;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.lib3270j.protocol.DS3270Constants.*;
|
||||
|
||||
public class QueryReplyBuilderTest {
|
||||
|
||||
private final EbcdicTranslator translator = new EbcdicTranslator();
|
||||
private final ScreenBuffer screen = new ScreenBuffer(TerminalModel.IBM_3279_4, translator);
|
||||
private final QueryReplyBuilder qrBuilder = new QueryReplyBuilder(screen);
|
||||
|
||||
@Test
|
||||
public void testBuildAllQueryReplies() {
|
||||
byte[] replies = qrBuilder.buildAllQueryReplies(80, 43, 80 * 43);
|
||||
assertNotNull(replies);
|
||||
assertTrue(replies.length > 0);
|
||||
assertEquals((byte) AID_SF, replies[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuildFilteredQueryRepliesWithSupportedCodes() {
|
||||
byte[] requested = new byte[] { (byte) QR_DDM, (byte) QR_USABLE_AREA };
|
||||
byte[] replies = qrBuilder.buildQueryReplies(requested, 80, 43, 80 * 43);
|
||||
|
||||
assertNotNull(replies);
|
||||
assertEquals((byte) AID_SF, replies[0]);
|
||||
|
||||
// First SF should be DDM: length (2 bytes), SFID_QREPLY (0x81), QR_DDM (0x95)
|
||||
int len1 = ((replies[1] & 0xFF) << 8) | (replies[2] & 0xFF);
|
||||
assertEquals(0x81, replies[3] & 0xFF);
|
||||
assertEquals(QR_DDM, replies[4] & 0xFF);
|
||||
|
||||
// Second SF should be Usable Area
|
||||
int pos2 = 1 + len1;
|
||||
int len2 = ((replies[pos2] & 0xFF) << 8) | (replies[pos2 + 1] & 0xFF);
|
||||
assertEquals(0x81, replies[pos2 + 2] & 0xFF);
|
||||
assertEquals(QR_USABLE_AREA, replies[pos2 + 3] & 0xFF);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuildFilteredQueryRepliesWithUnsupportedCode() {
|
||||
byte[] requested = new byte[] { (byte) 0x77 }; // Unsupported code
|
||||
byte[] replies = qrBuilder.buildQueryReplies(requested, 80, 43, 80 * 43);
|
||||
|
||||
assertNotNull(replies);
|
||||
assertEquals((byte) AID_SF, replies[0]);
|
||||
// Should emit QR_NULL (0xFF)
|
||||
assertEquals(0x81, replies[3] & 0xFF);
|
||||
assertEquals(QR_NULL, replies[4] & 0xFF);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package org.lib3270j.ft;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class FTConfigTest {
|
||||
|
||||
@Test
|
||||
public void testTsoReceiveAscii() {
|
||||
FTConfig config = new FTConfig();
|
||||
config.setHostType(FTConfig.HostType.TSO);
|
||||
config.setDirection(FTConfig.Direction.RECEIVE);
|
||||
config.setHostFilename("MY.DATASET");
|
||||
config.setTransferMode(FTConfig.TransferMode.ASCII);
|
||||
config.setCrAction(FTConfig.CrAction.REMOVE);
|
||||
|
||||
assertEquals("IND$FILE GET MY.DATASET ASCII CRLF", config.buildCommand());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTsoReceiveBinary() {
|
||||
FTConfig config = new FTConfig();
|
||||
config.setHostType(FTConfig.HostType.TSO);
|
||||
config.setDirection(FTConfig.Direction.RECEIVE);
|
||||
config.setHostFilename("'USER.BIN.DATA'");
|
||||
config.setTransferMode(FTConfig.TransferMode.BINARY);
|
||||
|
||||
assertEquals("IND$FILE GET 'USER.BIN.DATA'", config.buildCommand());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTsoSendFixedRecfm() {
|
||||
FTConfig config = new FTConfig();
|
||||
config.setHostType(FTConfig.HostType.TSO);
|
||||
config.setDirection(FTConfig.Direction.SEND);
|
||||
config.setHostFilename("MY.DATASET");
|
||||
config.setTransferMode(FTConfig.TransferMode.ASCII);
|
||||
config.setCrAction(FTConfig.CrAction.REMOVE);
|
||||
config.setRecfm("F");
|
||||
config.setLrecl("80");
|
||||
config.setBlksize("3120");
|
||||
|
||||
assertEquals("IND$FILE PUT MY.DATASET ASCII CRLF RECFM(F) LRECL(80) BLKSIZE(3120)", config.buildCommand());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCmsReceiveBinaryNoNakedParen() {
|
||||
FTConfig config = new FTConfig();
|
||||
config.setHostType(FTConfig.HostType.CMS);
|
||||
config.setDirection(FTConfig.Direction.RECEIVE);
|
||||
config.setHostFilename("PROFILE EXEC A");
|
||||
config.setTransferMode(FTConfig.TransferMode.BINARY);
|
||||
|
||||
// In CMS, binary receive has no options, so NO open parenthesis '(' should be generated!
|
||||
assertEquals("IND$FILE GET PROFILE EXEC A", config.buildCommand());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCmsReceiveAscii() {
|
||||
FTConfig config = new FTConfig();
|
||||
config.setHostType(FTConfig.HostType.CMS);
|
||||
config.setDirection(FTConfig.Direction.RECEIVE);
|
||||
config.setHostFilename("TEST DATA A");
|
||||
config.setTransferMode(FTConfig.TransferMode.ASCII);
|
||||
config.setCrAction(FTConfig.CrAction.REMOVE);
|
||||
|
||||
assertEquals("IND$FILE GET TEST DATA A (ASCII CRLF", config.buildCommand());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCmsSendWithRecfmAndLrecl() {
|
||||
FTConfig config = new FTConfig();
|
||||
config.setHostType(FTConfig.HostType.CMS);
|
||||
config.setDirection(FTConfig.Direction.SEND);
|
||||
config.setHostFilename("TEST FILE A");
|
||||
config.setTransferMode(FTConfig.TransferMode.ASCII);
|
||||
config.setCrAction(FTConfig.CrAction.REMOVE);
|
||||
config.setRecfm("V");
|
||||
config.setLrecl("132");
|
||||
|
||||
assertEquals("IND$FILE PUT TEST FILE A (ASCII CRLF RECFM V LRECL 132", config.buildCommand());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.lib3270j.protocol;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.lib3270j.protocol.DS3270Constants.*;
|
||||
|
||||
public class DS3270ConstantsTest {
|
||||
|
||||
@Test
|
||||
public void test12BitAddressRoundTrip() {
|
||||
int rows = 24;
|
||||
int cols = 80;
|
||||
int maxAddr = rows * cols; // 1920
|
||||
|
||||
for (int addr = 0; addr < maxAddr; addr += 17) {
|
||||
byte[] encoded = encodeAddress(addr, rows, cols);
|
||||
assertEquals(2, encoded.length);
|
||||
int decoded = decodeAddress(encoded[0] & 0xFF, encoded[1] & 0xFF);
|
||||
assertEquals(addr, decoded, "Address " + addr + " failed round trip");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test14BitAddressRoundTrip() {
|
||||
int rows = 60;
|
||||
int cols = 80; // 4800 (> 4096, triggers 14-bit format)
|
||||
int maxAddr = rows * cols;
|
||||
|
||||
for (int addr = 0; addr < maxAddr; addr += 123) {
|
||||
byte[] encoded = encodeAddress(addr, rows, cols);
|
||||
assertEquals(2, encoded.length);
|
||||
int decoded = decodeAddress(encoded[0] & 0xFF, encoded[1] & 0xFF);
|
||||
assertEquals(addr, decoded, "14-bit address " + addr + " failed round trip");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFieldAttributePredicates() {
|
||||
int protectedHighMod = FA_PRINTABLE | FA_PROTECT | FA_INT_HIGH_SEL | FA_MODIFY;
|
||||
assertTrue(faIsProtected(protectedHighMod));
|
||||
assertTrue(faIsHigh(protectedHighMod));
|
||||
assertTrue(faIsModified(protectedHighMod));
|
||||
assertFalse(faIsNumeric(protectedHighMod));
|
||||
assertFalse(faIsSkip(protectedHighMod));
|
||||
|
||||
int skipField = FA_PRINTABLE | FA_PROTECT | FA_NUMERIC;
|
||||
assertTrue(faIsSkip(skipField));
|
||||
assertTrue(faIsProtected(skipField));
|
||||
assertTrue(faIsNumeric(skipField));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package org.lib3270j.screen;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lib3270j.TerminalModel;
|
||||
import org.lib3270j.charset.EbcdicTranslator;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.lib3270j.protocol.DS3270Constants.*;
|
||||
|
||||
public class ScreenBufferTest {
|
||||
|
||||
private final EbcdicTranslator translator = new EbcdicTranslator();
|
||||
private final ScreenBuffer screen = new ScreenBuffer(TerminalModel.IBM_3279_4, translator);
|
||||
|
||||
@Test
|
||||
public void testScreenInitialization() {
|
||||
assertEquals(24, screen.getRows());
|
||||
assertEquals(80, screen.getCols());
|
||||
assertEquals(43, screen.getMaxRows());
|
||||
assertEquals(80, screen.getMaxCols());
|
||||
assertFalse(screen.isFormatted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScreenEraseAlternate() {
|
||||
screen.erase(true);
|
||||
assertTrue(screen.isScreenAlt());
|
||||
assertEquals(43, screen.getRows());
|
||||
assertEquals(80, screen.getCols());
|
||||
|
||||
screen.erase(false);
|
||||
assertFalse(screen.isScreenAlt());
|
||||
assertEquals(24, screen.getRows());
|
||||
assertEquals(80, screen.getCols());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFieldNavigationAndFindAttribute() {
|
||||
screen.erase(false);
|
||||
// Place field attribute at position 0 (unprotected)
|
||||
screen.setCellFA(0, (byte) FA_PRINTABLE);
|
||||
// Place field attribute at position 20 (protected)
|
||||
screen.setCellFA(20, (byte) (FA_PRINTABLE | FA_PROTECT));
|
||||
|
||||
assertTrue(screen.isFormatted());
|
||||
assertEquals(0, screen.findFieldAttribute(5));
|
||||
assertEquals(20, screen.findFieldAttribute(25));
|
||||
|
||||
// findNextUnprotected
|
||||
int nextUnprot = screen.findNextUnprotected(0);
|
||||
assertEquals(1, nextUnprot);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGraphicEscapeTranslation() {
|
||||
screen.erase(false);
|
||||
// Set cell at position 10 to horizontal line (0xA2) with CS_GE (0x04)
|
||||
ExtendedAttribute ea = screen.getCell(10);
|
||||
ea.ec = (byte) 0xA2;
|
||||
ea.cs = (byte) CS_GE;
|
||||
|
||||
screen.translateToUnicode();
|
||||
assertEquals('\u2500', ea.ucs4); // '─'
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user