mirror of
https://github.com/lihop/godot-xterm.git
synced 2025-05-03 20:14:22 +02:00
Add/update more files
This commit is contained in:
parent
3307231b65
commit
0769592a1b
44 changed files with 4188 additions and 362 deletions
|
@ -25,7 +25,7 @@ class TestBuffer:
|
|||
|
||||
|
||||
func handle_csi(params):
|
||||
calls.append(['csi', params])
|
||||
calls.append(['csi', params.to_array()])
|
||||
|
||||
|
||||
func clear():
|
||||
|
@ -68,7 +68,7 @@ func test_prints_printables():
|
|||
func skip_test_c0():
|
||||
for code in C0.values():
|
||||
parser.set_execute_handler(code, buffer, 'handle_exec')
|
||||
parse(parser, Decoder.string_from_codepoint(code))
|
||||
parse(parser, char(code))
|
||||
if code == 0x0 or code == 0x1b or code == 0x20 or code == 0x7f:
|
||||
assert_eq(buffer.calls, [])
|
||||
else:
|
||||
|
@ -81,7 +81,7 @@ func skip_test_c0():
|
|||
func skip_test_c1():
|
||||
for code in C1.values():
|
||||
parser.set_execute_handler(code, buffer, 'handle_exec')
|
||||
parse(parser, Decoder.string_from_codepoint(code))
|
||||
parse(parser, char(code))
|
||||
assert_eq(buffer.calls, [['exec']], 'code: 0x%x' % code)
|
||||
assert_eq(buffer.printed, '')
|
||||
parser.reset()
|
||||
|
|
|
@ -12,6 +12,6 @@ __meta__ = {
|
|||
"_edit_use_anchors_": false
|
||||
}
|
||||
_yield_between_tests = false
|
||||
_directory1 = "res://test/unit"
|
||||
_directory2 = "res://test/integration"
|
||||
_include_subdirectories = true
|
||||
_directory1 = "res://test"
|
||||
_double_strategy = 1
|
||||
|
|
66
test/test_utils.gd
Normal file
66
test/test_utils.gd
Normal file
|
@ -0,0 +1,66 @@
|
|||
# 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 Buffer = preload("res://addons/godot_xterm/buffer/buffer.gd")
|
||||
const BufferSet = preload("res://addons/godot_xterm/buffer/buffer_set.gd")
|
||||
const OptionsService = preload("res://addons/godot_xterm/services/options_service.gd")
|
||||
|
||||
|
||||
class MockBufferService:
|
||||
extends Reference
|
||||
|
||||
|
||||
signal resized(cols, rows)
|
||||
|
||||
var service_brand
|
||||
var buffer setget ,_get_buffer
|
||||
var buffers
|
||||
var is_user_scrolling: bool = false
|
||||
var cols
|
||||
var rows
|
||||
|
||||
|
||||
func _get_buffer():
|
||||
return buffers.active
|
||||
|
||||
|
||||
func _init(cols: int, rows: int, options_service = MockOptionsService.new()):
|
||||
self.cols = cols
|
||||
self.rows = rows
|
||||
buffers = BufferSet.new(options_service, self)
|
||||
|
||||
|
||||
func resize(cols: int, rows: int) -> void:
|
||||
self.cols = cols
|
||||
self.rows = rows
|
||||
|
||||
|
||||
func reset() -> void:
|
||||
pass
|
||||
|
||||
|
||||
class MockOptionsService:
|
||||
extends Reference
|
||||
|
||||
|
||||
signal option_changed
|
||||
|
||||
var service_brand
|
||||
var options = OptionsService.TerminalOptions.new()
|
||||
|
||||
|
||||
func _init(test_options = null):
|
||||
if test_options:
|
||||
for key in test_options.keys():
|
||||
self.options.set(key, test_options[key])
|
||||
|
||||
|
||||
func set_option(key: String, value) -> void:
|
||||
pass
|
||||
|
||||
|
||||
func get_option(key: String):
|
||||
pass
|
BIN
test/unit/.test_input_handler.gd.swp
Normal file
BIN
test/unit/.test_input_handler.gd.swp
Normal file
Binary file not shown.
128
test/unit/buffer/test_buffer.gd
Normal file
128
test/unit/buffer/test_buffer.gd
Normal 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)
|
||||
|
||||
|
||||
|
||||
|
348
test/unit/buffer/test_buffer_line.gd
Normal file
348
test/unit/buffer/test_buffer_line.gd
Normal 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, '1', 2, '1'.ord_at(0)])
|
||||
assert_eq(cell.get_as_char_data(), [123, '1', 2, '1'.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), '')
|
|
@ -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
|
|
@ -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)
|
202
test/unit/parser/test_parser.gd
Normal file
202
test/unit/parser/test_parser.gd
Normal 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]])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
35
test/unit/renderer/test_canvas_rendering_context_2d.gd
Normal file
35
test/unit/renderer/test_canvas_rendering_context_2d.gd
Normal 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)
|
38
test/unit/renderer/test_character_joiner_registry.gd
Normal file
38
test/unit/renderer/test_character_joiner_registry.gd
Normal 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), [])
|
218
test/unit/test_input_handler.gd
Normal file
218
test/unit/test_input_handler.gd
Normal 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(["¥¥", "¥"]))
|
Loading…
Add table
Add a link
Reference in a new issue