Add/update more files

This commit is contained in:
Leroy Hopson 2020-05-10 22:56:49 +12:00
parent 3307231b65
commit 0769592a1b
44 changed files with 4188 additions and 362 deletions

Binary file not shown.

View file

@ -0,0 +1,128 @@
# Copyright (c) 2017 The xterm.js authors. All rights reserved.
# Ported to GDScript by the GodotXterm authors.
# License MIT
extends "res://addons/gut/test.gd"
const Buffer = preload("res://addons/godot_xterm/buffer/buffer.gd")
const CircularList = preload("res://addons/godot_xterm/circular_list.gd")
const CellData = preload("res://addons/godot_xterm/buffer/cell_data.gd")
const AttributeData = preload("res://addons/godot_xterm/buffer/attribute_data.gd")
const TestUtils = preload("res://test/test_utils.gd")
class BaseBufferTest:
extends "res://addons/gut/test.gd"
const INIT_COLS = 80
const INIT_ROWS = 24
const INIT_SCROLLBACK = 1000
var options_service
var buffer_service
var buffer
func before_each():
options_service = TestUtils.MockOptionsService.new({'scrollback': INIT_SCROLLBACK})
buffer_service = TestUtils.MockBufferService.new(INIT_COLS, INIT_ROWS)
buffer = Buffer.new(true, options_service, buffer_service)
class TestInit:
extends BaseBufferTest
func test_buffer_lines():
assert_eq(buffer.lines.get_script(), CircularList)
assert_eq(buffer.lines.max_length, buffer_service.rows + INIT_SCROLLBACK)
func test_buffer_scroll_bottom():
assert_eq(buffer.scroll_bottom, buffer_service.rows - 1)
func test_fill_viewport_rows():
# It should fill the buffer with blank lines based on the size of the viewport
var blank_line_char = buffer.get_blank_line(AttributeData.new()).load_cell(0, CellData.new()).get_as_char_data()
buffer.fill_viewport_rows()
assert_eq(buffer.lines.length, INIT_ROWS)
for y in range(INIT_ROWS):
assert_eq(buffer.lines.get_el(y).length, INIT_COLS)
for x in range(INIT_COLS):
assert_eq(buffer.lines.get_el(y).load_cell(x, CellData.new()).get_as_char_data(), blank_line_char)
class TestGetWrappedRangeForLine:
extends BaseBufferTest
func before_each():
.before_each()
buffer.fill_viewport_rows()
func test_non_wrapped_returns_a_single_row_for_the_first_row():
assert_eq(buffer.get_wrapped_range_for_line(0).first, 0)
assert_eq(buffer.get_wrapped_range_for_line(0).last, 0)
func test_non_wrapped_returns_a_single_row_for_a_middle_row():
assert_eq(buffer.get_wrapped_range_for_line(12).first, 12)
assert_eq(buffer.get_wrapped_range_for_line(12).last, 12)
func test_non_wrapped_returns_a_single_row_for_the_last_row():
assert_eq(buffer.get_wrapped_range_for_line(buffer.lines.length - 1).first, INIT_ROWS - 1)
assert_eq(buffer.get_wrapped_range_for_line(buffer.lines.length - 1).last, INIT_ROWS - 1)
func test_wrapped_returns_a_range_for_first_row():
buffer.lines.get_el(1).is_wrapped = true
assert_eq(buffer.get_wrapped_range_for_line(0).first, 0)
assert_eq(buffer.get_wrapped_range_for_line(0).last, 1)
func test_wrapped_range_for_middle_row_wrapping_upwards():
buffer.fill_viewport_rows()
buffer.lines.get_el(12).is_wrapped = true
assert_eq(buffer.get_wrapped_range_for_line(12).first, 11)
assert_eq(buffer.get_wrapped_range_for_line(12).last, 12)
func test_wrapped_range_for_middle_row_wrapping_downwards():
buffer.lines.get_el(13).is_wrapped = true
assert_eq(buffer.get_wrapped_range_for_line(12).first, 12)
assert_eq(buffer.get_wrapped_range_for_line(12).last, 13)
func test_wrapped_range_for_middle_row_wrapping_both_ways():
buffer.lines.get_el(11).is_wrapped = true
buffer.lines.get_el(12).is_wrapped = true
buffer.lines.get_el(13).is_wrapped = true
buffer.lines.get_el(14).is_wrapped = true
assert_eq(buffer.get_wrapped_range_for_line(12).first, 10)
assert_eq(buffer.get_wrapped_range_for_line(12).last, 14)
func test_wrapped_range_for_last_row():
buffer.lines.get_el(INIT_ROWS - 1).is_wrapped = true
assert_eq(buffer.get_wrapped_range_for_line(buffer.lines.length - 1).first, INIT_ROWS - 2)
assert_eq(buffer.get_wrapped_range_for_line(buffer.lines.length - 1).last, INIT_ROWS - 1)
func test_wrapped_range_for_row_that_wraps_upward_to_first_row():
buffer.lines.get_el(1).is_wrapped = true
assert_eq(buffer.get_wrapped_range_for_line(1).first, 0)
assert_eq(buffer.get_wrapped_range_for_line(1).last, 1)
func test_wrapped_range_for_row_that_wraps_downward_to_last_row():
buffer.lines.get_el(buffer.lines.length - 1).is_wrapped = true
assert_eq(buffer.get_wrapped_range_for_line(buffer.lines.length - 2).first, INIT_ROWS - 2)
assert_eq(buffer.get_wrapped_range_for_line(buffer.lines.length - 2).last, INIT_ROWS - 1)

View file

@ -0,0 +1,348 @@
# Copyright (c) 2018 The xterm.js authors. All rights reserved.
# Ported to GDScript by the GodotXterm authors.
# License MIT
extends "res://addons/gut/test.gd"
const BufferLine = preload("res://addons/godot_xterm/buffer/buffer_line.gd")
const AttributeData = preload("res://addons/godot_xterm/buffer/attribute_data.gd")
const CellData = preload("res://addons/godot_xterm/buffer/cell_data.gd")
const Decoder = preload("res://addons/godot_xterm/input/text_decoder.gd")
const Constants = preload("res://addons/godot_xterm/buffer/constants.gd")
const BgFlags = Constants.BgFlags
const Attributes = Constants.Attributes
const UnderlineStyle = Constants.UnderlineStyle
const FgFlags = Constants.FgFlags
const Content = Constants.Content
class BufferLineTest:
extends BufferLine
func _init(cols: int, fill_cell_data = null, is_wrapped: bool = false).(cols, fill_cell_data, is_wrapped):
pass
func to_array():
var result = []
for i in range(length):
result.append(load_cell(i, CellData.new()).get_as_char_data())
return result
class TestAttributeData:
extends "res://addons/gut/test.gd"
var attrs
func before_each():
attrs = AttributeData.new()
func test_has_extended_attrs():
assert_eq(attrs.has_extended_attrs() as bool, false)
attrs.bg |= BgFlags.HAS_EXTENDED
assert_eq(attrs.has_extended_attrs() as bool, true)
func test_get_underline_color_P256():
# set a P256 color
attrs.extended.underline_color = Attributes.CM_P256 | 45
# should use FG color if BgFlags.HAS_EXTENDED is not set
assert_eq(attrs.get_underline_color(), -1)
# should use underline_color is BgFlags.HAS_EXTENDED is set and underline_color holds a value
attrs.bg |= BgFlags.HAS_EXTENDED
assert_eq(attrs.get_underline_color(), 45)
# should use FG color if underline_color holds no value
attrs.extended.underline_color = -1
attrs.fg |= Attributes.CM_P256 | 123
assert_eq(attrs.get_underline_color(), 123)
func test_get_underline_color_RGB():
# set a P256 color
attrs.extended.underline_color = Attributes.CM_RGB | (1 << 16) | (2 << 8) | 3
# should use FG color if BgFlags.HAS_EXTENDED is not set
assert_eq(attrs.get_underline_color(), -1)
# should use underline_color if BgFlags.HAS_EXTENDED is set and underline_color holds a value
attrs.bg |= BgFlags.HAS_EXTENDED
assert_eq(attrs.get_underline_color(), (1 << 16) | (2 << 8) | 3)
# should use FG color if underline_color holds no value
attrs.extended.underline_color = -1
attrs.fg |= Attributes.CM_P256 | 123
assert_eq(attrs.get_underline_color(), 123)
func test_underline_attrs():
# should always return color mode of fg
for mode in [Attributes.CM_DEFAULT, Attributes.CM_P16, Attributes.CM_P256, Attributes.CM_RGB]:
attrs.extended.underline_color = mode
assert_eq(attrs.get_underline_color_mode(), attrs.get_fg_color_mode())
assert_eq(attrs.is_underline_color_default(), true)
attrs.fg = Attributes.CM_RGB
for mode in [Attributes.CM_DEFAULT, Attributes.CM_P16, Attributes.CM_P256, Attributes.CM_RGB]:
attrs.extended.underline_color = mode
assert_eq(attrs.get_underline_color_mode(), attrs.get_fg_color_mode())
assert_eq(attrs.is_underline_color_default(), false)
assert_eq(attrs.is_underline_color_rgb(), true)
# should return own mode
attrs.bg |= BgFlags.HAS_EXTENDED
attrs.extended.underline_color = Attributes.CM_DEFAULT
assert_eq(attrs.get_underline_color_mode(), Attributes.CM_DEFAULT)
attrs.extended.underline_color = Attributes.CM_P16
assert_eq(attrs.get_underline_color_mode(), Attributes.CM_P16)
assert_eq(attrs.is_underline_color_palette(), true)
attrs.extended.underline_color = Attributes.CM_P256
assert_eq(attrs.get_underline_color_mode(), Attributes.CM_P256)
assert_eq(attrs.is_underline_color_palette(), true)
attrs.extended.underline_color = Attributes.CM_RGB
assert_eq(attrs.get_underline_color_mode(), Attributes.CM_RGB)
assert_eq(attrs.is_underline_color_rgb(), true)
func test_get_underline_style():
# defaults to no underline style
assert_eq(attrs.get_underline_style(), UnderlineStyle.NONE)
# should return NONE if UNDERLINE is not set
attrs.extended.underline_style = UnderlineStyle.CURLY
assert_eq(attrs.get_underline_style(), UnderlineStyle.NONE)
# should return SINGLE style if UNDERLINE is set and HAS_EXTENDED is false
attrs.fg |= FgFlags.UNDERLINE
assert_eq(attrs.get_underline_style(), UnderlineStyle.SINGLE)
# shoud return correct style if both is set
attrs.bg |= BgFlags.HAS_EXTENDED
assert_eq(attrs.get_underline_style(), UnderlineStyle.CURLY)
# should return NONE if UNDERLINE is not set, but HAS_EXTENDED is true
attrs.fg &= ~FgFlags.UNDERLINE
assert_eq(attrs.get_underline_style(), UnderlineStyle.NONE)
class TestCellData:
extends "res://addons/gut/test.gd"
var cell
var decoder = Decoder.Utf8ToUtf32.new()
func before_each():
cell = CellData.new()
func test_char_data_cell_data_equality():
# ASCII
cell.set_from_char_data([123, 'a', 1, 'a'.ord_at(0)])
assert_eq(cell.get_as_char_data(), [123, 'a', 1, 'a'.ord_at(0)])
assert_eq(cell.is_combined(), 0)
# combining
cell.set_from_char_data([123, 'e\u0301', 1, '\u0301'.ord_at(0)])
assert_eq(cell.get_as_char_data(), [123, 'e\u0301', 1, '\u0301'.ord_at(0)])
assert_eq(cell.is_combined(), Content.IS_COMBINED_MASK)
# surrogate
cell.set_from_char_data([123, '𝄞', 1, 0x1D11E])
assert_eq(cell.get_as_char_data(), [123, '𝄞', 1, 0x1D11E])
assert_eq(cell.is_combined(), 0)
# surrogate + combining
cell.set_from_char_data([123, '𓂀\u0301', 1, '𓂀\u0301'.ord_at(1)])
assert_eq(cell.get_as_char_data(), [123, '𓂀\u0301', 1, '𓂀\u0301'.ord_at(1)])
assert_eq(cell.is_combined(), Content.IS_COMBINED_MASK)
# wide char
cell.set_from_char_data([123, '', 2, ''.ord_at(0)])
assert_eq(cell.get_as_char_data(), [123, '', 2, ''.ord_at(0)])
assert_eq(cell.is_combined(), 0)
class TestBufferLine:
extends "res://addons/gut/test.gd"
func test_ctor():
var line = BufferLineTest.new(0)
assert_eq(line.length, 0)
assert_eq(line.is_wrapped, false)
line = BufferLineTest.new(10)
assert_eq(line.length, 10)
assert_eq(line.load_cell(0, CellData.new()).get_as_char_data(),
[0, Constants.NULL_CELL_CHAR, Constants.NULL_CELL_WIDTH,
Constants.NULL_CELL_CODE])
assert_eq(line.is_wrapped, false)
line = BufferLineTest.new(10, null, true)
assert_eq(line.length, 10)
assert_eq(line.load_cell(0, CellData.new()).get_as_char_data(),
[0, Constants.NULL_CELL_CHAR, Constants.NULL_CELL_WIDTH,
Constants.NULL_CELL_CODE])
assert_eq(line.is_wrapped, true)
var char_data = [123, 'a', 456, 'a'.ord_at(0)]
line = BufferLineTest.new(10, CellData.from_char_data(char_data), true)
assert_eq(line.length, 10)
assert_eq(line.load_cell(0, CellData.new()).get_as_char_data(), char_data)
assert_eq(line.is_wrapped, true)
func test_insert_cells() -> void:
var line = BufferLineTest.new(3)
line.set_cell(0, CellData.from_char_data([1, 'a', 0, 'a'.ord_at(0)]))
line.set_cell(1, CellData.from_char_data([2, 'b', 0, 'b'.ord_at(0)]))
line.set_cell(2, CellData.from_char_data([3, 'c', 0, 'c'.ord_at(0)]))
line.insert_cells(1, 3, CellData.from_char_data([4, 'd', 0, 'd'.ord_at(0)]))
assert_eq(line.to_array(), [
[1, 'a', 0, 'a'.ord_at(0)],
[4, 'd', 0, 'd'.ord_at(0)],
[4, 'd', 0, 'd'.ord_at(0)]
])
func test_delete_cells() -> void:
var line = BufferLineTest.new(5)
line.set_cell(0, CellData.from_char_data([1, 'a', 0, 'a'.ord_at(0)]))
line.set_cell(1, CellData.from_char_data([2, 'b', 0, 'b'.ord_at(0)]))
line.set_cell(2, CellData.from_char_data([3, 'c', 0, 'c'.ord_at(0)]))
line.set_cell(3, CellData.from_char_data([4, 'd', 0, 'd'.ord_at(0)]))
line.set_cell(4, CellData.from_char_data([5, 'e', 0, 'e'.ord_at(0)]))
line.delete_cells(1, 2, CellData.from_char_data([6, 'f', 0, 'f'.ord_at(0)]))
assert_eq(line.to_array(), [
[1, 'a', 0, 'a'.ord_at(0)],
[4, 'd', 0, 'd'.ord_at(0)],
[5, 'e', 0, 'e'.ord_at(0)],
[6, 'f', 0, 'f'.ord_at(0)],
[6, 'f', 0, 'f'.ord_at(0)]
])
func test_replace_cells():
var line = BufferLineTest.new(5)
line.set_cell(0, CellData.from_char_data([1, 'a', 0, 'a'.ord_at(0)]))
line.set_cell(1, CellData.from_char_data([2, 'b', 0, 'b'.ord_at(0)]))
line.set_cell(2, CellData.from_char_data([3, 'c', 0, 'c'.ord_at(0)]))
line.set_cell(3, CellData.from_char_data([4, 'd', 0, 'd'.ord_at(0)]))
line.set_cell(4, CellData.from_char_data([5, 'e', 0, 'e'.ord_at(0)]))
line.replace_cells(2, 4, CellData.from_char_data([6, 'f', 0, 'f'.ord_at(0)]))
assert_eq(line.to_array(), [
[1, 'a', 0, 'a'.ord_at(0)],
[2, 'b', 0, 'b'.ord_at(0)],
[6, 'f', 0, 'f'.ord_at(0)],
[6, 'f', 0, 'f'.ord_at(0)],
[5, 'e', 0, 'e'.ord_at(0)],
])
# Skipped a bunch of tests here...
class TestAddCharToCell:
extends "res://addons/gut/test.gd"
var line
var cell
func before_each():
line = BufferLineTest.new(3, CellData.from_char_data([Constants.DEFAULT_ATTR,
Constants.NULL_CELL_CHAR, Constants.NULL_CELL_WIDTH, Constants.NULL_CELL_CODE]))
cell = line.load_cell(0, CellData.new())
func test_sets_width_to_1_for_empty_cell():
line.add_codepoint_to_cell(0, "\u0301".ord_at(0))
cell = line.load_cell(0, CellData.new())
# chars contains single combining char
# width is set to 1
assert_eq(cell.get_as_char_data(), [Constants.DEFAULT_ATTR, '\u0301', 1, 0x0301])
# do not account a single combining char as combined
assert_eq(cell.is_combined(), 0)
func test_add_char_to_combining_string_in_cell():
cell.set_from_char_data([123, "e\u0301", 1, "e\u0301".ord_at(1)])
line.set_cell(0, cell)
line.add_codepoint_to_cell(0, "\u0301".ord_at(0))
line.load_cell(0, cell)
# char contains 3 chars
# width is set to 1
assert_eq(cell.get_as_char_data(), [123, "e\u0301\u0301", 1, 0x0301])
# do not account a single combining char as combined
assert_eq(cell.is_combined(), Content.IS_COMBINED_MASK)
func test_create_combining_string_on_taken_cell():
cell.set_from_char_data([123, "e", 1, "e".ord_at(1)])
line.set_cell(0, cell)
line.add_codepoint_to_cell(0, "\u0301".ord_at(0))
line.load_cell(0, cell)
# chars contains 2 chars
# width is set to 1
assert_eq(cell.get_as_char_data(), [123, "e\u0301", 1, 0x0301])
# do not account a single combining char as combined
assert_eq(cell.is_combined(), Content.IS_COMBINED_MASK)
class Testtranslate_to_string:
extends "res://addons/gut/test.gd"
var line
func before_each():
line = BufferLineTest.new(10, CellData.from_char_data([Constants.DEFAULT_ATTR,
Constants.NULL_CELL_CHAR, Constants.NULL_CELL_WIDTH, Constants.NULL_CELL_CODE]), false)
func test_empty_line():
assert_eq(line.translate_to_string(false), ' ')
assert_eq(line.translate_to_string(true), '')
func test_ASCII():
line.set_cell(0, CellData.from_char_data([1, 'a', 1, 'a'.ord_at(0)]))
line.set_cell(2, CellData.from_char_data([1, 'a', 1, 'a'.ord_at(0)]))
line.set_cell(4, CellData.from_char_data([1, 'a', 1, 'a'.ord_at(0)]))
line.set_cell(5, CellData.from_char_data([1, 'a', 1, 'a'.ord_at(0)]))
assert_eq(line.translate_to_string(false), 'a a aa ')
assert_eq(line.translate_to_string(true), 'a a aa')
assert_eq(line.translate_to_string(false, 0, 5), 'a a a')
assert_eq(line.translate_to_string(false, 0, 4), 'a a ')
assert_eq(line.translate_to_string(false, 0, 3), 'a a')
assert_eq(line.translate_to_string(true, 0, 5), 'a a a')
assert_eq(line.translate_to_string(true, 0, 4), 'a a ')
assert_eq(line.translate_to_string(true, 0, 3), 'a a')
func test_space_at_end():
line.set_cell(0, CellData.from_char_data([1, 'a', 1, 'a'.ord_at(0)]))
line.set_cell(2, CellData.from_char_data([1, 'a', 1, 'a'.ord_at(0)]))
line.set_cell(4, CellData.from_char_data([1, 'a', 1, 'a'.ord_at(0)]))
line.set_cell(5, CellData.from_char_data([1, 'a', 1, 'a'.ord_at(0)]))
line.set_cell(6, CellData.from_char_data([1, ' ', 1, ' '.ord_at(0)]))
assert_eq(line.translate_to_string(false), 'a a aa ')
assert_eq(line.translate_to_string(true), 'a a aa ')
func test_always_returns_some_sane_value():
# sanity check - broken line with invalid out of bound null width cells
# this can atm happen with deleting/inserting chars in inputhandler by "breaking"
# fullwidth pairs --> needs to be fixed after settling BufferLine impl
assert_eq(line.translate_to_string(false), ' ')
assert_eq(line.translate_to_string(true), '')
func test_works_with_end_col_0():
line.set_cell(0, CellData.from_char_data([1, 'a', 1, 'a'.ord_at(0)]))
assert_eq(line.translate_to_string(true, 0, 0), '')

View file

@ -16,9 +16,10 @@ const TEST_STRINGS = [
"모든 국민은 행위시의 법률에 의하여 범죄를 구성하지 아니하는 행위로 소추되지 아니하며. 전직대통령의 신분과 예우에 관하여는 법률로 정한다, 국회는 헌법 또는 법률에 특별한 규정이 없는 한 재적의원 과반수의 출석과 출석의원 과반수의 찬성으로 의결한다. 군인·군무원·경찰공무원 기타 법률이 정하는 자가 전투·훈련등 직무집행과 관련하여 받은 손해에 대하여는 법률이 정하는 보상외에 국가 또는 공공단체에 공무원의 직무상 불법행위로 인한 배상은 청구할 수 없다.",
"كان فشكّل الشرقي مع, واحدة للمجهود تزامناً بعض بل. وتم جنوب للصين غينيا لم, ان وبدون وكسبت الأمور ذلك, أسر الخاسر الانجليزية هو. نفس لغزو مواقعها هو. الجو علاقة الصعداء انه أي, كما مع بمباركة للإتحاد الوزراء. ترتيب الأولى أن حدى, الشتوية باستحداث مدن بل, كان قد أوسع عملية. الأوضاع بالمطالبة كل قام, دون إذ شمال الربيع،. هُزم الخاصّة ٣٠ أما, مايو الصينية مع قبل.",
"או סדר החול מיזמי קרימינולוגיה. קהילה בגרסה לויקיפדים אל היא, של צעד ציור ואלקטרוניקה. מדע מה ברית המזנון ארכיאולוגיה, אל טבלאות מבוקשים כלל. מאמרשיחהצפה העריכהגירסאות שכל אל, כתב עיצוב מושגי של. קבלו קלאסיים ב מתן. נבחרים אווירונאוטיקה אם מלא, לוח למנוע ארכיאולוגיה מה. ארץ לערוך בקרבת מונחונים או, עזרה רקטות לויקיפדים אחר גם.",
"Лорем ლორემ अधिकांश 覧六子 八メル 모든 בקרבת 💮 😂 äggg 123€ 𝄞.",
"Лорем ლორემ अधिकांश 覧六子 八メル 모든 בקרבת äggg 123€ .",
]
func test_utf32_to_utf8():
# 1 byte utf8 character
assert_eq(
@ -45,10 +46,6 @@ func test_utf32_to_utf8():
PoolByteArray([0xf0, 0x9f, 0x90, 0xa7]) as Array
)
func test_string_from_codepoint():
assert_eq(Decoder.string_from_codepoint(49), '1')
assert_eq(Decoder.string_from_codepoint(0x1f427), '🐧')
assert_eq(Decoder.string_from_codepoint(0x1d11e), '𝄞')
func test_utf32_to_string():
assert_eq(
@ -71,6 +68,11 @@ class TestUtf8ToUtf32Decoder:
decoder.clear()
target.clear()
target.resize(5)
func test_lol():
var target = [0, 0, 0, 0]
decoder.decode('<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>'.substr(0, 1).to_utf8(), target)
assert_eq(target, [])
func test_full_code_point_0_to_65535(): # 1/2/3 byte sequences

View file

@ -36,7 +36,7 @@ class TestTerminal:
func handle_execute(code: int):
var flag = Decoder.string_from_codepoint(code)
var flag = char(code)
calls.append(['exe', flag])
@ -137,14 +137,14 @@ func test_state_GROUND_execute_action():
var exes = range(0x00, 0x18) + [0x19] + range(0x1c, 0x20)
for exe in exes:
parser.current_state = ParserState.GROUND
parse(parser, Decoder.string_from_codepoint(exe))
parse(parser, char(exe))
assert_eq(parser.current_state, ParserState.GROUND)
parser.reset()
func test_state_GROUND_print_action():
var printables = range(0x20, 0x7f) # NOTE: DEL excluded
for printable in printables:
var string = Decoder.string_from_codepoint(printable)
var string = char(printable)
parser.current_state = ParserState.GROUND
parse(parser, string)
assert_eq(parser.current_state, ParserState.GROUND)
@ -204,7 +204,7 @@ func test_state_ESCAPE_execute_rules():
var exes = range(0x00, 0x18) + [0x19] + range(0x1c, 0x20)
for exe in exes:
parser.current_state = ParserState.ESCAPE
var data = Decoder.string_from_codepoint(exe)
var data = char(exe)
parse(parser, data)
assert_eq(parser.current_state, ParserState.ESCAPE, 'exe: %x' % exe)
assert_eq(test_terminal.calls, [['exe', data]], 'exe: %x' % exe)
@ -222,7 +222,7 @@ func test_trans_ESCAPE_to_GROUND_with_esc_dispatch_action():
var dispatches = range(0x30, 0x50) + range(0x51, 0x58) + [0x59, 0x5a] + range(0x60, 0x7f)
for dispatch in dispatches:
parser.current_state = ParserState.ESCAPE
var data = Decoder.string_from_codepoint(dispatch)
var data = char(dispatch)
parse(parser, data)
assert_eq(parser.current_state, ParserState.GROUND,
'wrong state: %s, dispatch: %x' % [ParserState.keys()[parser.current_state], dispatch])
@ -236,7 +236,7 @@ func test_trans_ESCAPE_to_ESCAPE_INTERMEDIATE_with_collect_action():
var collect = range(0x20, 0x30)
for c in collect:
parser.current_state = ParserState.ESCAPE
var data = Decoder.string_from_codepoint(c)
var data = char(c)
parse(parser, data)
assert_eq(parser.current_state, ParserState.ESCAPE_INTERMEDIATE)
assert_eq(parser.collect, data)
@ -246,7 +246,7 @@ func test_trans_ESCAPE_to_ESCAPE_INTERMEDIATE_with_collect_action():
func test_state_ESCAPE_INTERMEDIATE_execute_rules():
var exes = range(0x00, 0x18) + [0x19] + range(0x1c, 0x20)
for exe in exes:
var data = Decoder.string_from_codepoint(exe)
var data = char(exe)
parser.current_state = ParserState.ESCAPE_INTERMEDIATE
parse(parser, data)
assert_eq(parser.current_state, ParserState.ESCAPE_INTERMEDIATE)
@ -265,7 +265,7 @@ func test_state_ESCAPE_INTERMEDIATE_ignore():
func test_state_ESCAPE_INTERMEDIATE_collect_action():
var collect = range(0x20, 0x30)
for c in collect:
var data = Decoder.string_from_codepoint(c)
var data = char(c)
parser.current_state = ParserState.ESCAPE_INTERMEDIATE
parse(parser, data)
assert_eq(parser.current_state, ParserState.ESCAPE_INTERMEDIATE)
@ -276,7 +276,7 @@ func test_state_ESCAPE_INTERMEDIATE_collect_action():
func test_trans_ESCAPE_INTERMEDIATE_to_GROUND_with_esc_dispatch_action():
var collect = range(0x30, 0x7f)
for c in collect:
var data = Decoder.string_from_codepoint(c)
var data = char(c)
parser.current_state = ParserState.ESCAPE_INTERMEDIATE
parse(parser, data)
assert_eq(parser.current_state, ParserState.GROUND)
@ -309,7 +309,7 @@ func test_ANYWHERE_or_ESCAPE_to_CSI_ENTRY_with_clear():
func test_CSI_ENTRY_execute_rules():
var exes = range(0x00, 0x18) + [0x19] + range(0x1c, 0x20)
for exe in exes:
var data = Decoder.string_from_codepoint(exe)
var data = char(exe)
parser.current_state = ParserState.CSI_ENTRY
parse(parser, data)
assert_eq(parser.current_state, ParserState.CSI_ENTRY)
@ -328,7 +328,7 @@ func test_state_CSI_ENTRY_ignore():
func test_trans_CSI_ENTRY_to_GROUND_with_csi_dispatch_action():
var dispatches = range(0x40, 0x7f)
for dispatch in dispatches:
var data = Decoder.string_from_codepoint(dispatch)
var data = char(dispatch)
parser.current_state = ParserState.CSI_ENTRY
parse(parser, data)
assert_eq(parser.current_state, ParserState.GROUND)
@ -342,7 +342,7 @@ func test_trans_CSI_ENTRY_to_CSI_PARAMS_with_param_or_collect_action():
var collect = ['\u003c', '\u003d', '\u003e', '\u003f']
for param in params:
parser.current_state = ParserState.CSI_ENTRY
parse(parser, Decoder.string_from_codepoint(param))
parse(parser, char(param))
assert_eq(parser.current_state, ParserState.CSI_PARAM)
assert_eq(parser.params, [param - 48], 'param: 0x%x' % param)
parser.reset()
@ -362,7 +362,7 @@ func test_trans_CSI_ENTRY_to_CSI_PARAMS_with_param_or_collect_action():
func test_state_CSI_PARAM_execute_rules():
var exes = range(0x00, 0x018) + [0x19] + range(0x1c, 0x20)
for exe in exes:
var data = Decoder.string_from_codepoint(exe)
var data = char(exe)
parser.current_state = ParserState.CSI_PARAM
parse(parser, data)
assert_eq(parser.current_state, ParserState.CSI_PARAM)
@ -375,7 +375,7 @@ func test_state_CSI_PARAM_param_action():
var params = range(0x30, 0x3a)
for param in params:
parser.current_state = ParserState.CSI_PARAM
parse(parser, Decoder.string_from_codepoint(param))
parse(parser, char(param))
assert_eq(parser.current_state, ParserState.CSI_PARAM)
assert_eq(parser.params, [param - 48], 'param: 0x%x' % param)
parser.reset()
@ -391,7 +391,7 @@ func test_state_CSI_PARAM_ignore():
func test_trans_CSI_PARAM_to_GROUND_with_csi_dispatch_action():
var dispatches = range(0x40, 0x7f)
for dispatch in dispatches:
var data = Decoder.string_from_codepoint(dispatch)
var data = char(dispatch)
parser.current_state = ParserState.CSI_PARAM
parser.params = [0, 1]
parse(parser, data)
@ -403,7 +403,7 @@ func test_trans_CSI_PARAM_to_GROUND_with_csi_dispatch_action():
func test_trans_CSI_ENTRY_to_CSI_INTERMEDIATE_with_collect_action():
for collect in range(0x20, 0x30):
var data = Decoder.string_from_codepoint(collect)
var data = char(collect)
parser.current_state = ParserState.CSI_ENTRY
parse(parser, data)
assert_eq(parser.current_state, ParserState.CSI_INTERMEDIATE)

View file

@ -0,0 +1,202 @@
# Copyright (c) 2019 The xterm.js authors. All rights reserved.
# Ported to GDScript by the GodotXterm authors.
# License MIT
extends 'res://addons/gut/test.gd'
const Params = preload("res://addons/godot_xterm/parser/params.gd")
class TestParams:
extends 'res://addons/gut/test.gd'
var params
func before_each():
params = Params.new()
func test_respects_ctor_args():
params = Params.new(12, 23)
assert_eq(params.params.size(), 12)
assert_eq(params.sub_params.size(), 23)
assert_eq(params.to_array(), [])
func test_add_param():
params.add_param(1)
assert_eq(params.length, 1)
assert_eq(params.params.slice(0, params.length - 1), [1])
assert_eq(params.to_array(), [1])
params.add_param(23)
assert_eq(params.length, 2)
assert_eq(params.params.slice(0, params.length - 1), [1, 23])
assert_eq(params.to_array(), [1, 23])
assert_eq(params.sub_params_length, 0)
func test_add_sub_param():
params.add_param(1)
params.add_sub_param(2)
params.add_sub_param(3)
assert_eq(params.length, 1)
assert_eq(params.sub_params_length, 2)
assert_eq(params.to_array(), [1, [2, 3]])
params.add_param(12345)
params.add_sub_param(-1)
assert_eq(params.length, 2)
assert_eq(params.sub_params_length, 3)
assert_eq(params.to_array(), [1, [2,3], 12345, [-1]])
func test_should_not_add_sub_params_without_previous_param():
params.add_sub_param(2)
params.add_sub_param(3)
assert_eq(params.length, 0)
assert_eq(params.sub_params_length, 0)
assert_eq(params.to_array(), [])
params.add_param(1)
params.add_sub_param(2)
params.add_sub_param(3)
assert_eq(params.length, 1)
assert_eq(params.sub_params_length, 2)
assert_eq(params.to_array(), [1, [2, 3]])
func test_reset():
params.add_param(1)
params.add_sub_param(2)
params.add_sub_param(3)
params.add_param(12345)
params.reset()
assert_eq(params.length, 0)
assert_eq(params.sub_params_length, 0)
assert_eq(params.to_array(), [])
params.add_param(1)
params.add_sub_param(2)
params.add_sub_param(3)
params.add_param(12345)
params.add_sub_param(-1)
assert_eq(params.length, 2)
assert_eq(params.sub_params_length, 3)
assert_eq(params.to_array(), [1, [2, 3], 12345, [-1]])
func test_from_array_to_array():
var data = []
assert_eq(params.from_array(data).to_array(), data)
data = [1, [2, 3], 12345, [-1]]
assert_eq(params.from_array(data).to_array(), data)
data = [38, 2, 50, 100, 150]
assert_eq(params.from_array(data).to_array(), data)
data = [38, 2, 50, 100, [150]]
assert_eq(params.from_array(data).to_array(), data)
data = [38, [2, 50, 100, 150]]
assert_eq(params.from_array(data).to_array(), data)
# strip empty sub params
data = [38, [2, 50, 100, 150], 5, [], 6]
assert_eq(Params.from_array(data).to_array(), [38, [2, 50, 100, 150], 5, 6])
# ignore leading sub params
data = [[1,2], 12345, [-1]]
assert_eq(Params.from_array(data).to_array(), [12345, [-1]])
class TestParse:
extends 'res://addons/gut/test.gd'
var params
func parse(params, s):
params.reset()
params.add_param(0)
if typeof(s) == TYPE_STRING:
s = [s]
for chunk in s:
var i = 0
while i < chunk.length():
# Start for
var code = chunk.to_ascii()[i]
var do = true
while do:
match code:
0x3b:
params.add_param(0)
0x3a:
params.add_sub_param(-1)
_:
params.add_digit(code - 48)
code = chunk.to_ascii()[i] if i < chunk.length() else 0
i+=1
do = i < s.size() and code > 0x2f and code < 0x3c
i-=1
# End for
i+=1
func before_each():
params = Params.new()
func test_param_defaults_to_0(): # ZDM (Zero Default Mode)
parse(params, '')
assert_eq(params.to_array(), [0])
func test_sub_param_defaults_to_neg_1():
parse(params, ':')
assert_eq(params.to_array(), [0, [-1]])
func test_reset_on_new_sequence():
parse(params, '1;2;3')
assert_eq(params.to_array(), [1, 2, 3])
parse(params, '4')
assert_eq(params.to_array(), [4])
parse(params, '4::123:5;6;7')
assert_eq(params.to_array(), [4, [-1, 123, 5], 6, 7])
parse(params, '')
assert_eq(params.to_array(), [0])
func test_should_handle_length_restrictions_correctly():
params = Params.new(3, 3)
parse(params, '1;2;3')
assert_eq(params.to_array(), [1, 2, 3])
parse(params, '4')
assert_eq(params.to_array(), [4])
parse(params, '4::123:5;6;7')
assert_eq(params.to_array(), [4, [-1, 123, 5], 6, 7])
parse(params, '')
assert_eq(params.to_array(), [0])
# overlong params
parse(params, '4;38:2::50:100:150;48:5:22')
assert_eq(params.to_array(), [4, 38, [2, -1, 50], 48])
# overlong sub params
parse(params, '4;38:2::50:100:150;48:5:22')
assert_eq(params.to_array(), [4, 38, [2, -1, 50], 48])
func test_typical_sequences():
# SGR with semicolon syntax
parse(params, '0;4;38;2;50;100;150;48;5;22')
assert_eq(params.to_array(), [0, 4, 38, 2, 50, 100, 150, 48, 5, 22])
# SGR mixed style (partly wrong)
parse(params, '0;4;38;2;50:100:150;48;5:22')
assert_eq(params.to_array(), [0, 4, 38, 2, 50, [100, 150], 48, 5, [22]])
# SGR colon style
parse(params, '0;4;38:2::50:100:150;48:5:22')
assert_eq(params.to_array(), [0, 4, 38, [2, -1, 50, 100, 150], 48, [5, 22]])
func test_clamp_parsed_params():
parse(params, '2147483648')
assert_eq(params.to_array(), [0x7FFFFFFF])
func test_clamp_parsed_sub_params():
parse(params, ':2147483648')
assert_eq(params.to_array(), [0, [0x7FFFFFFF]])
func test_should_cancel_subdigits_if_beyond_params_limit():
parse(params, ';;;;;;;;;10;;;;;;;;;;20;;;;;;;;;;30;31;32;33;34;35::::::::')
assert_eq(params.to_array(), [
0, 0, 0, 0, 0, 0, 0, 0, 0, 10,
0, 0, 0, 0, 0, 0, 0, 0, 0, 20,
0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, 32
])
# func test_should_carry_forward_is_sub_state():
# parse(params, ['1:22:33', '44'])
# assert_eq(params.to_array(), [1, [22, 3344]])

View file

@ -0,0 +1,35 @@
# Copyright 2020 The GodotXterm authors. All rights reserved.
# License MIT
extends "res://addons/gut/test.gd"
const CanvasRenderingContext2D = preload("res://addons/godot_xterm/renderer/canvas_rendering_context_2d.gd")
const RegularFont = preload("res://addons/godot_xterm/fonts/source_code_pro/source_code_pro_regular.tres")
const BoldFont = preload("res://addons/godot_xterm/fonts/source_code_pro/source_code_pro_bold.tres")
var ctx
func before_each():
ctx = CanvasRenderingContext2D.new()
func test_measure_text():
assert_eq(ctx.measure_text("a").width, RegularFont.get_string_size("a").x)
func test_save_and_restore():
# fill_style
ctx.fill_style = Color.red
ctx.save()
ctx.fill_style = Color.blue
assert_eq(ctx.fill_style, Color.blue)
ctx.restore()
assert_eq(ctx.fill_style, Color.red)
# font
ctx.font = RegularFont
ctx.save()
ctx.font = BoldFont
assert_eq(ctx.font, BoldFont)
ctx.restore()
assert_eq(ctx.font, RegularFont)

View file

@ -0,0 +1,38 @@
# Copyright (c) 2018 The xterm.js authors. All rights reserved.
# Ported to GDScript by the GodotXterm authors.
# License MIT
extends "res://addons/gut/test.gd"
const CharacterJoinerRegistry = preload("res://addons/godot_xterm/renderer/character_joiner_registry.gd")
const Buffer = preload("res://addons/godot_xterm/buffer/buffer.gd")
const BufferLine = preload("res://addons/godot_xterm/buffer/buffer_line.gd")
const CircularList = preload("res://addons/godot_xterm/circular_list.gd")
const CellData = preload("res://addons/godot_xterm/buffer/cell_data.gd")
const AttributeData = preload("res://addons/godot_xterm/buffer/attribute_data.gd")
const TestUtils = preload("res://test/test_utils.gd")
var registry
func line_data(data):
var tline = BufferLine.new(0)
for d in data:
var line = d[0]
var attr = d[1] if d.size() > 1 else 0
var offset = tline.length
tline.resize(tline.length + line.split('').size(), CellData.from_char_data([0, '', 0, 0]))
func before_each():
var buffer_service = TestUtils.MockBufferService.new(16, 10)
var lines = buffer_service.buffer.lines
lines.set_el(0, line_data([['a -> b -> c -> d']]))
lines.set_el(1, line_data([['a -> b => c -> d']]))
lines.set_el(2, line_data([['a -> b -', 0xFFFFFFFF], ['> c -> d', 0]]))
registry = CharacterJoinerRegistry.new(buffer_service)
func test_has_no_joiners_upon_creation():
assert_eq(registry.get_joined_characters(0), [])

View file

@ -0,0 +1,218 @@
# Copyright (c) 2017 The xterm.js authors. All rights reserved.
# Ported to GDScript by the GodotXterm authors.
# License MIT
extends "res://addons/gut/test.gd"
const TestUtils = preload("res://test/test_utils.gd")
const InputHandler = preload("res://addons/godot_xterm/input_handler.gd")
const CharsetService = preload("res://addons/godot_xterm/services/charset_service.gd")
const Params = preload("res://addons/godot_xterm/parser/params.gd")
const CoreService = preload("res://addons/godot_xterm/services/core_service.gd")
var options_service
var buffer_service
var charset_service
var core_service
var input_handler
func get_lines(buffer_service, limit: int) -> Array:
var res = []
if not limit:
limit = buffer_service.rows
for i in range(limit):
var line = buffer_service.buffer.lines.get_el(i)
if line:
res.append(line.translate_to_string(true))
return res
func repeat(string: String, times: int) -> String:
var s = ""
for i in range(times):
s += string
return s
func term_content(buffer_service, trim: bool) -> PoolStringArray:
var result = PoolStringArray([])
for i in buffer_service.rows:
result.append(buffer_service.buffer.lines.get_el(i).translate_to_string(trim))
return result;
func before_each():
options_service = TestUtils.MockOptionsService.new()
buffer_service = TestUtils.MockBufferService.new(80, 30, options_service)
charset_service = CharsetService.new()
core_service = CoreService.new()
input_handler = InputHandler.new(buffer_service, core_service, charset_service, options_service)
# Skipping lots of tests here...
func test_erase_in_line():
buffer_service = TestUtils.MockBufferService.new(10, 3, options_service)
input_handler = InputHandler.new(buffer_service, core_service, charset_service, options_service)
# fill 6 lines to test 3 different states
input_handler.parse(repeat("a", buffer_service.cols))
input_handler.parse(repeat("a", buffer_service.cols))
input_handler.parse(repeat("a", buffer_service.cols))
# params[0] - right erase
buffer_service.buffer.y = 0
buffer_service.buffer.x = 7
input_handler.erase_in_line(Params.from_array([0]))
assert_eq(buffer_service.buffer.lines.get_el(0).translate_to_string(false),
repeat("a", 7) + " ")
# # params[1] - left erase
# buffer_service.buffer.y = 1
# buffer_service.buffer.x = 70
# input_handler.erase_in_line(Params.from_array([1]))
# assert_eq(buffer_service.buffer.lines.get_el(1).translate_to_string(false),
# repeat(" ", 70) + " aaaaaaaaa")
#
# # params[1] - left erase
# buffer_service.buffer.y = 2
# buffer_service.buffer.x = 70
# input_handler.erase_in_line(Params.from_array([2]))
# assert_eq(buffer_service.buffer.lines.get_el(2).translate_to_string(false),
# repeat(" ", buffer_service.cols))
func skip_test_erase_in_display():
buffer_service = TestUtils.MockBufferService.new(80, 7, options_service)
input_handler = InputHandler.new(buffer_service, core_service, charset_service, options_service)
# fill display with a's
for _i in range(buffer_service.rows):
input_handler.parse(repeat("a", buffer_service.cols))
# params [0] - right and below erase
buffer_service.buffer.y = 5
buffer_service.buffer.x = 40
input_handler.erase_in_display(Params.from_array([0]))
assert_eq(term_content(buffer_service, false), PoolStringArray([
repeat("a", buffer_service.cols),
repeat("a", buffer_service.cols),
repeat("a", buffer_service.cols),
repeat("a", buffer_service.cols),
repeat("a", buffer_service.cols),
repeat("a", 40) + repeat(" ", buffer_service.cols - 40),
repeat(" ", buffer_service.cols),
]))
assert_eq(term_content(buffer_service, true), PoolStringArray([
repeat("a", buffer_service.cols),
repeat("a", buffer_service.cols),
repeat("a", buffer_service.cols),
repeat("a", buffer_service.cols),
repeat("a", buffer_service.cols),
repeat("a", 40),
""
]))
# reset
for _i in range(buffer_service.rows):
input_handler.parse(repeat("a", buffer_service.cols))
# params [1] - left and above
buffer_service.buffer.y = 5;
buffer_service.buffer.x = 40;
input_handler.erase_in_display(Params.from_array([1]))
assert_eq(term_content(buffer_service, false), PoolStringArray([
repeat(" ", buffer_service.cols),
repeat(" ", buffer_service.cols),
repeat(" ", buffer_service.cols),
repeat(" ", buffer_service.cols),
repeat(" ", buffer_service.cols),
repeat(" ", 41) + repeat("a", buffer_service.cols - 41),
repeat("a", buffer_service.cols),
]))
assert_eq(term_content(buffer_service, true), PoolStringArray([
"",
"",
"",
"",
"",
repeat(" ", 41) + repeat("a", buffer_service.cols - 41),
repeat("a", buffer_service.cols),
]))
# reset
for _i in range(buffer_service.rows):
input_handler.parse(repeat("a", buffer_service.cols))
# params [2] - whole screen
buffer_service.buffer.y = 5;
buffer_service.buffer.x = 40;
input_handler.erase_in_display(Params.from_array([2]));
assert_eq(term_content(buffer_service, false), PoolStringArray([
repeat(" ", buffer_service.cols),
repeat(" ", buffer_service.cols),
repeat(" ", buffer_service.cols),
repeat(" ", buffer_service.cols),
repeat(" ", buffer_service.cols),
repeat(" ", buffer_service.cols),
repeat(" ", buffer_service.cols),
]))
assert_eq(term_content(buffer_service, true), PoolStringArray([
"",
"",
"",
"",
"",
"",
"",
]))
#
# # reset and add a wrapped line
# buffer_service.buffer.y = 0;
# buffer_service.buffer.x = 0;
# input_handler.parse(Array(buffer_service.cols + 1).join('a')); # line 0
# input_handler.parse(Array(buffer_service.cols + 10).join('a')); # line 1 and 2
# for (let i = 3; i < buffer_service.rows; ++i) input_handler.parse(Array(buffer_service.cols + 1).join('a'));
#
# # params[1] left and above with wrap
# # confirm precondition that line 2 is wrapped
# expect(buffer_service.buffer.lines.get(2)!.isWrapped).true;
# buffer_service.buffer.y = 2;
# buffer_service.buffer.x = 40;
# input_handler.erase_in_display(Params.from_array([1]));
# expect(buffer_service.buffer.lines.get(2)!.isWrapped).false;
#
# # reset and add a wrapped line
# buffer_service.buffer.y = 0;
# buffer_service.buffer.x = 0;
# input_handler.parse(Array(buffer_service.cols + 1).join('a')); # line 0
# input_handler.parse(Array(buffer_service.cols + 10).join('a')); # line 1 and 2
# for (let i = 3; i < buffer_service.rows; ++i) input_handler.parse(Array(buffer_service.cols + 1).join('a'));
#
# # params[1] left and above with wrap
# # confirm precondition that line 2 is wrapped
# expect(buffer_service.buffer.lines.get(2)!.isWrapped).true;
# buffer_service.buffer.y = 1;
# buffer_service.buffer.x = 90; # Cursor is beyond last column
# input_handler.erase_in_display(Params.from_array([1]));
# expect(buffer_service.buffer.lines.get(2)!.isWrapped).false;
func test_print_does_not_cause_an_infinite_loop():
var container = []
container.resize(10)
container[0] = 0x200B
input_handler.print(container, 0, 1)
# FIXME
func skip_test_clear_cells_to_the_right_on_early_wrap_around():
buffer_service.resize(5, 5)
options_service.options.scrollback = 1
input_handler.parse('12345')
buffer_service.buffer.x = 0
input_handler.parse("¥¥¥")
assert_eq(get_lines(buffer_service, 2), PoolStringArray(["¥¥", ""]))