mirror of
https://github.com/lihop/godot-xterm.git
synced 2025-05-03 20:14:22 +02:00
Remove gdscript version and replace with native
Former-commit-id: f9474fe533
This commit is contained in:
parent
f8412a03f5
commit
a022104230
126 changed files with 116 additions and 14221 deletions
|
@ -1,102 +0,0 @@
|
|||
# Copyright (c) 2020 The GodotXterm authors. All rights reserved.
|
||||
# License MIT
|
||||
extends "res://addons/gut/test.gd"
|
||||
|
||||
const Parser = preload("res://addons/godot_xterm/parser/escape_sequence_parser.gd")
|
||||
const Terminal = preload("res://addons/godot_xterm/terminal.gd")
|
||||
const Decoder = preload("res://addons/godot_xterm/input/text_decoder.gd")
|
||||
const Constants = preload("res://addons/godot_xterm/parser/constants.gd")
|
||||
|
||||
const C0 = Constants.C0
|
||||
const C1 = Constants.C1
|
||||
|
||||
class TestBuffer:
|
||||
var calls = []
|
||||
var printed = ''
|
||||
|
||||
func handle_print(data, start, end):
|
||||
var string = Decoder.utf32_to_string(data.slice(start, end - 1))
|
||||
calls.append(['print', string])
|
||||
printed += string
|
||||
|
||||
|
||||
func handle_exec():
|
||||
calls.append(['exec'])
|
||||
|
||||
|
||||
func handle_csi(params):
|
||||
calls.append(['csi', params.to_array()])
|
||||
|
||||
|
||||
func clear():
|
||||
printed = ''
|
||||
calls.resize(0)
|
||||
|
||||
|
||||
var parser
|
||||
var buffer
|
||||
var decoder
|
||||
|
||||
|
||||
func parse(parser, string):
|
||||
var container = []
|
||||
container.resize(string.length())
|
||||
var length = decoder.decode(string.to_utf8(), container)
|
||||
parser.parse(container, length)
|
||||
|
||||
|
||||
func before_all():
|
||||
buffer = TestBuffer.new()
|
||||
decoder = Decoder.Utf8ToUtf32.new()
|
||||
|
||||
|
||||
func before_each():
|
||||
parser = Parser.new()
|
||||
parser.set_print_handler(buffer, 'handle_print')
|
||||
buffer.clear()
|
||||
|
||||
|
||||
func test_prints_printables():
|
||||
var string = 'bash-4.4# '
|
||||
var data = string.to_utf8()
|
||||
var length = decoder.decode(data, data)
|
||||
parser.parse(data, length)
|
||||
assert_eq(buffer.calls, [['print', 'bash-4.4# ']])
|
||||
assert_eq(buffer.printed, 'bash-4.4# ')
|
||||
|
||||
|
||||
func skip_test_c0():
|
||||
for code in C0.values():
|
||||
parser.set_execute_handler(code, buffer, 'handle_exec')
|
||||
parse(parser, char(code))
|
||||
if code == 0x0 or code == 0x1b or code == 0x20 or code == 0x7f:
|
||||
assert_eq(buffer.calls, [])
|
||||
else:
|
||||
assert_eq(buffer.calls, [['exec']], 'code: 0x%x' % code)
|
||||
assert_eq(buffer.printed, '')
|
||||
parser.reset()
|
||||
buffer.clear()
|
||||
|
||||
|
||||
func skip_test_c1():
|
||||
for code in C1.values():
|
||||
parser.set_execute_handler(code, buffer, 'handle_exec')
|
||||
parse(parser, char(code))
|
||||
assert_eq(buffer.calls, [['exec']], 'code: 0x%x' % code)
|
||||
assert_eq(buffer.printed, '')
|
||||
parser.reset()
|
||||
buffer.clear()
|
||||
|
||||
|
||||
func test_print_csi_print():
|
||||
parser.set_csi_handler({'final': 'g'}, buffer, 'handle_csi')
|
||||
parse(parser, 'a\u001b[gb')
|
||||
assert_eq(buffer.calls, [['print', 'a'],['csi', [0]], ['print', 'b']])
|
||||
assert_eq(buffer.printed, 'ab')
|
||||
|
||||
|
||||
func test_csi_position_cursor():
|
||||
parser.set_csi_handler({'final': 'H'}, buffer, 'handle_csi')
|
||||
parse(parser, '\u001b[1;5H')
|
||||
assert_eq(buffer.calls, [['csi', [1, 5]]])
|
||||
assert_eq(buffer.printed, '')
|
|
@ -1,17 +0,0 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/gut/gut.gd" type="Script" id=1]
|
||||
|
||||
[node name="Gut" type="Control"]
|
||||
self_modulate = Color( 1, 1, 1, 0 )
|
||||
margin_right = 1031.0
|
||||
margin_bottom = 597.0
|
||||
rect_min_size = Vector2( 740, 250 )
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
_yield_between_tests = false
|
||||
_include_subdirectories = true
|
||||
_directory1 = "res://test"
|
||||
_double_strategy = 1
|
|
@ -1,66 +0,0 @@
|
|||
# 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
|
Binary file not shown.
|
@ -1,362 +0,0 @@
|
|||
# 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)
|
||||
|
||||
|
||||
class TestResize:
|
||||
extends BaseBufferTest
|
||||
|
||||
|
||||
func before_each():
|
||||
.before_each()
|
||||
buffer.fill_viewport_rows()
|
||||
|
||||
|
||||
func test_column_size_reduction_trims_data_in_the_buffer():
|
||||
buffer.resize(INIT_COLS / 2, INIT_ROWS)
|
||||
assert_eq(buffer.lines.length, INIT_ROWS)
|
||||
for i in range(INIT_ROWS):
|
||||
assert_eq(buffer.lines.get_line(i).length, INIT_COLS / 2)
|
||||
|
||||
|
||||
func test_column_size_increase_adds_pad_columns():
|
||||
buffer.resize(INIT_COLS + 10, INIT_ROWS)
|
||||
assert_eq(buffer.lines.length, INIT_ROWS)
|
||||
for i in range(INIT_ROWS):
|
||||
assert_eq(buffer.lines.get_line(i).length, INIT_COLS + 10)
|
||||
|
||||
|
||||
func test_row_size_reduction_trims_blank_lines_from_the_end():
|
||||
buffer.resize(INIT_COLS, INIT_ROWS - 10)
|
||||
assert_eq(buffer.lines.length, INIT_ROWS - 10)
|
||||
|
||||
|
||||
func test_row_size_reduction_moves_viewport_down_when_it_is_at_the_end():
|
||||
# Set cursor y to have 5 blank lines below it
|
||||
buffer.y = INIT_ROWS - 5 - 1
|
||||
buffer.resize(INIT_COLS, INIT_ROWS - 10)
|
||||
# Trim 5 rows
|
||||
assert_eq(buffer.lines.length, INIT_ROWS - 5)
|
||||
# Shift the viewport down 5 rows
|
||||
assert_eq(buffer.ydisp, 5)
|
||||
assert_eq(buffer.ybase, 5)
|
||||
|
||||
|
||||
func test_no_scrollback_trims_from_the_top_of_the_buffer_when_the_cursor_reaches_the_bottom():
|
||||
buffer = Buffer.new(true, TestUtils.MockOptionsService.new({"scrollback": 0}), buffer_service)
|
||||
assert_eq(buffer.lines.max_length, INIT_ROWS)
|
||||
buffer.y = INIT_ROWS - 1
|
||||
buffer.fill_viewport_rows()
|
||||
var ch_data = buffer.lines.get_line(5).load_cell(0, CellData.new()).get_as_char_data()
|
||||
ch_data[1] = "a"
|
||||
buffer.lines.get_line(5).set_cell(0, CellData.from_char_data(ch_data))
|
||||
ch_data = buffer.lines.get_line(INIT_ROWS - 1).load_cell(0, CellData.new()).get_as_char_data()
|
||||
ch_data[1] = "b"
|
||||
buffer.lines.get_line(INIT_ROWS - 1).set_cell(0, CellData.from_char_data(ch_data))
|
||||
buffer.resize(INIT_COLS, INIT_ROWS - 5)
|
||||
assert_eq(buffer.lines.get_line(0).load_cell(0, CellData.new()).get_as_char_data()[1], "a")
|
||||
assert_eq(buffer.lines.get_line(INIT_ROWS - 1 - 5).load_cell(0, CellData.new()).get_as_char_data()[1], "b")
|
||||
|
||||
|
||||
func test_row_size_increase_adds_blank_lines_to_empty_buffer():
|
||||
assert_eq(buffer.ydisp, 0)
|
||||
buffer.resize(INIT_COLS, INIT_ROWS + 10)
|
||||
assert_eq(buffer.ydisp, 0)
|
||||
assert_eq(buffer.lines.length, INIT_ROWS + 10)
|
||||
|
||||
func test_row_size_increase_shows_more_of_the_buffer_above():
|
||||
# Create 10 extra blank lines
|
||||
for i in range(10):
|
||||
buffer.lines.push(buffer.get_blank_line(AttributeData.new()))
|
||||
# Set cursor to the bottom of the buffer
|
||||
buffer.y = INIT_ROWS - 1
|
||||
# Scroll down 10 lines
|
||||
buffer.ybase = 10
|
||||
buffer.ydisp = 10
|
||||
assert_eq(buffer.lines.length, INIT_ROWS + 10)
|
||||
buffer.resize(INIT_COLS, INIT_ROWS + 5)
|
||||
# Should be 5 more lines
|
||||
assert_eq(buffer.ydisp, 5)
|
||||
assert_eq(buffer.ybase, 5)
|
||||
# Should not trim the buffer
|
||||
assert_eq(buffer.lines.length, INIT_ROWS + 10)
|
||||
|
||||
|
||||
func test_row_size_increase_shows_more_of_the_buffer_below_when_the_viewort_is_at_the_top_of_the_buffer():
|
||||
# Create 10 extra blank lines
|
||||
for i in range(10):
|
||||
buffer.lines.push(buffer.get_blank_line(AttributeData.new()))
|
||||
# Set cursor to the bottom of the buffer
|
||||
buffer.y = INIT_ROWS - 1
|
||||
# Scroll down 10 lines
|
||||
buffer.ybase = 10
|
||||
buffer.ydisp = 0
|
||||
assert_eq(buffer.lines.length, INIT_ROWS + 10)
|
||||
buffer.resize(INIT_COLS, INIT_ROWS + 5)
|
||||
# The viewport should remain at the top
|
||||
assert_eq(buffer.ydisp, 0)
|
||||
# The buffer ybase should move up 5 lines
|
||||
assert_eq(buffer.ybase, 5)
|
||||
# Should not trim the buffer
|
||||
assert_eq(buffer.lines.length, INIT_ROWS + 10)
|
||||
|
||||
|
||||
func test_row_and_column_increase_resizes_properly():
|
||||
buffer.resize(INIT_COLS + 5, INIT_ROWS + 5)
|
||||
assert_eq(buffer.lines.length, INIT_ROWS + 5)
|
||||
buffer.resize(INIT_COLS - 5, INIT_ROWS)
|
||||
assert_eq(buffer.lines.length, INIT_ROWS)
|
||||
|
||||
|
||||
func test_reflow_does_not_wrap_empty_lines():
|
||||
assert_eq(buffer.lines.length, INIT_ROWS)
|
||||
buffer.resize(INIT_COLS - 5, INIT_ROWS)
|
||||
assert_eq(buffer.lines.length, INIT_ROWS)
|
||||
|
||||
|
||||
func test_reflow_shrinks_row_length():
|
||||
buffer.resize(5, 10)
|
||||
assert_eq(buffer.lines.length, 10)
|
||||
for i in range(10):
|
||||
assert_eq(buffer.lines.get_line(i).length, 5)
|
||||
|
||||
|
||||
func test_reflow_wraps_and_unwraps_lines():
|
||||
buffer.resize(5, 10)
|
||||
var first_line = buffer.lines.get_line(0)
|
||||
for i in range(5):
|
||||
var code = "a".ord_at(0) + i
|
||||
var ch = char(code)
|
||||
first_line.set_cell(i, CellData.from_char_data([0, ch, 1, code]))
|
||||
buffer.y = 1
|
||||
assert_eq(buffer.lines.get_line(0).length, 5)
|
||||
assert_eq(buffer.lines.get_line(0).translate_to_string(), "abcde")
|
||||
buffer.resize(1, 10)
|
||||
assert_eq(buffer.lines.length, 10)
|
||||
assert_eq(buffer.lines.get_line(0).translate_to_string(), "a")
|
||||
assert_eq(buffer.lines.get_line(1).translate_to_string(), "b")
|
||||
assert_eq(buffer.lines.get_line(2).translate_to_string(), "c")
|
||||
assert_eq(buffer.lines.get_line(3).translate_to_string(), "d")
|
||||
assert_eq(buffer.lines.get_line(4).translate_to_string(), "e")
|
||||
assert_eq(buffer.lines.get_line(5).translate_to_string(), " ")
|
||||
assert_eq(buffer.lines.get_line(6).translate_to_string(), " ")
|
||||
assert_eq(buffer.lines.get_line(7).translate_to_string(), " ")
|
||||
assert_eq(buffer.lines.get_line(8).translate_to_string(), " ")
|
||||
assert_eq(buffer.lines.get_line(9).translate_to_string(), " ")
|
||||
buffer.resize(5, 10)
|
||||
assert_eq(buffer.lines.length, 10)
|
||||
assert_eq(buffer.lines.get_line(0).translate_to_string(), "abcde")
|
||||
assert_eq(buffer.lines.get_line(1).translate_to_string(), " ")
|
||||
assert_eq(buffer.lines.get_line(2).translate_to_string(), " ")
|
||||
assert_eq(buffer.lines.get_line(3).translate_to_string(), " ")
|
||||
assert_eq(buffer.lines.get_line(4).translate_to_string(), " ")
|
||||
assert_eq(buffer.lines.get_line(5).translate_to_string(), " ")
|
||||
assert_eq(buffer.lines.get_line(6).translate_to_string(), " ")
|
||||
assert_eq(buffer.lines.get_line(7).translate_to_string(), " ")
|
||||
assert_eq(buffer.lines.get_line(8).translate_to_string(), " ")
|
||||
assert_eq(buffer.lines.get_line(9).translate_to_string(), " ")
|
||||
|
||||
|
||||
func test_discards_parts_of_wrapped_lines_that_go_out_of_the_scrollback():
|
||||
options_service.options.scrollback = 1
|
||||
buffer.resize(10, 5)
|
||||
var last_line = buffer.lines.get_line(3)
|
||||
for i in range(10):
|
||||
var code = "a".ord_at(0) + i
|
||||
var ch = char(code)
|
||||
last_line.set_cell(i, CellData.from_char_data([0, ch, 1, code]))
|
||||
assert_eq(buffer.lines.length, 5)
|
||||
buffer.y = 4
|
||||
buffer.resize(2, 5)
|
||||
assert_eq(buffer.y, 4)
|
||||
assert_eq(buffer.ybase, 1)
|
||||
assert_eq(buffer.lines.get_line(0).translate_to_string(), "ab")
|
||||
assert_eq(buffer.lines.get_line(1).translate_to_string(), "cd")
|
||||
assert_eq(buffer.lines.get_line(2).translate_to_string(), "ef")
|
||||
assert_eq(buffer.lines.get_line(3).translate_to_string(), "gh")
|
||||
assert_eq(buffer.lines.get_line(4).translate_to_string(), "ij")
|
||||
assert_eq(buffer.lines.get_line(5).translate_to_string(), " ")
|
||||
buffer.resize(1, 5)
|
||||
assert_eq(buffer.y, 4)
|
||||
assert_eq(buffer.ybase, 1)
|
||||
assert_eq(buffer.lines.length, 6)
|
||||
assert_eq(buffer.lines.get_line(0).translate_to_string(), "f")
|
||||
assert_eq(buffer.lines.get_line(1).translate_to_string(), "g")
|
||||
assert_eq(buffer.lines.get_line(2).translate_to_string(), "h")
|
||||
assert_eq(buffer.lines.get_line(3).translate_to_string(), "i")
|
||||
assert_eq(buffer.lines.get_line(4).translate_to_string(), "j")
|
||||
assert_eq(buffer.lines.get_line(5).translate_to_string(), " ")
|
||||
buffer.resize(10, 5)
|
||||
assert_eq(buffer.y, 1)
|
||||
assert_eq(buffer.ybase, 0)
|
||||
assert_eq(buffer.lines.length, 5)
|
||||
assert_eq(buffer.lines.get_line(0).translate_to_string(), "fghij ")
|
||||
assert_eq(buffer.lines.get_line(1).translate_to_string(), " ")
|
||||
assert_eq(buffer.lines.get_line(2).translate_to_string(), " ")
|
||||
assert_eq(buffer.lines.get_line(3).translate_to_string(), " ")
|
||||
assert_eq(buffer.lines.get_line(4).translate_to_string(), " ")
|
||||
|
||||
|
||||
func test_removes_the_correct_amount_of_rows_when_reflowing_larger():
|
||||
# This is a regression test to ensure that successive wrapped lines that are getting
|
||||
# 3+ lines removed on a reflow actually remove the right lines
|
||||
buffer.resize(10, 10)
|
||||
buffer.y = 2
|
||||
var first_line = buffer.lines.get_line(0)
|
||||
var second_line = buffer.lines.get_line(1)
|
||||
for i in range(10):
|
||||
var code = "a".ord_at(0) + i
|
||||
var ch = char(code)
|
||||
first_line.set_cell(i, CellData.from_char_data([0, ch, 1, code]))
|
||||
for i in range(10):
|
||||
var code = "0".ord_at(0) + i
|
||||
var ch = char(code)
|
||||
second_line.set_cell(i, CellData.from_char_data([0, ch, 1, code]))
|
||||
assert_eq(buffer.lines.length, 10)
|
||||
assert_eq(buffer.lines.get_line(0).translate_to_string(), "abcdefghij")
|
||||
assert_eq(buffer.lines.get_line(1).translate_to_string(), "0123456789")
|
||||
for i in range(2, 10):
|
||||
assert_eq(buffer.lines.get_line(i).translate_to_string(), " ")
|
||||
buffer.resize(2, 10)
|
||||
assert_eq(buffer.ybase, 1)
|
||||
assert_eq(buffer.lines.length, 11)
|
||||
assert_eq(buffer.lines.get_line(0).translate_to_string(), "ab")
|
||||
assert_eq(buffer.lines.get_line(1).translate_to_string(), "cd")
|
||||
assert_eq(buffer.lines.get_line(2).translate_to_string(), "ef")
|
||||
assert_eq(buffer.lines.get_line(3).translate_to_string(), "gh")
|
||||
assert_eq(buffer.lines.get_line(4).translate_to_string(), "ij")
|
||||
assert_eq(buffer.lines.get_line(5).translate_to_string(), "01")
|
||||
assert_eq(buffer.lines.get_line(6).translate_to_string(), "23")
|
||||
assert_eq(buffer.lines.get_line(7).translate_to_string(), "45")
|
||||
assert_eq(buffer.lines.get_line(8).translate_to_string(), "67")
|
||||
assert_eq(buffer.lines.get_line(9).translate_to_string(), "89")
|
||||
assert_eq(buffer.lines.get_line(10).translate_to_string(), " ")
|
||||
buffer.resize(10, 10)
|
||||
assert_eq(buffer.ybase, 0)
|
||||
assert_eq(buffer.lines.length, 10)
|
||||
assert_eq(buffer.lines.get_line(0).translate_to_string(), "abcdefghij")
|
||||
assert_eq(buffer.lines.get_line(1).translate_to_string(), "0123456789")
|
||||
for i in range(2, 10):
|
||||
assert_eq(buffer.lines.get_line(i).translate_to_string(), " ",
|
||||
"line %d is incorrect" % i)
|
|
@ -1,436 +0,0 @@
|
|||
# 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)],
|
||||
])
|
||||
|
||||
|
||||
func test_copy_from():
|
||||
var line = BufferLineTest.new(5)
|
||||
line.set_cell(0, CellData.from_char_data([1, 'a', 0, 'a'.ord_at(0)]))
|
||||
line.set_cell(0, CellData.from_char_data([2, 'b', 0, 'b'.ord_at(0)]))
|
||||
line.set_cell(0, CellData.from_char_data([3, 'c', 0, 'c'.ord_at(0)]))
|
||||
line.set_cell(0, CellData.from_char_data([4, 'd', 0, 'd'.ord_at(0)]))
|
||||
line.set_cell(0, CellData.from_char_data([5, 'e', 0, 'e'.ord_at(0)]))
|
||||
var line2 = BufferLineTest.new(5, CellData.from_char_data([1, 'a', 0, 'a'.ord_at(0)]), true)
|
||||
line2.copy_from(line)
|
||||
assert_eq(line2.to_array(), line.to_array())
|
||||
assert_eq(line2.length, line.length)
|
||||
assert_eq(line2.is_wrapped, line.is_wrapped)
|
||||
|
||||
|
||||
class TestResize:
|
||||
extends "res://addons/gut/test.gd"
|
||||
|
||||
|
||||
var CHAR_DATA = [1, 'a', 0, 'a'.ord_at(0)]
|
||||
var line
|
||||
|
||||
func repeat(el, times: int) -> Array:
|
||||
var result = []
|
||||
result.resize(times)
|
||||
for i in range(times):
|
||||
result[i] = el
|
||||
return result
|
||||
|
||||
|
||||
func test_enlarge():
|
||||
line = BufferLineTest.new(5, CellData.from_char_data(CHAR_DATA), false)
|
||||
line.resize(10, CellData.from_char_data(CHAR_DATA))
|
||||
assert_eq(line.to_array(), repeat(CHAR_DATA, 10))
|
||||
|
||||
|
||||
func test_shrink():
|
||||
line = BufferLineTest.new(10, CellData.from_char_data(CHAR_DATA), false)
|
||||
line.resize(5, CellData.from_char_data(CHAR_DATA))
|
||||
assert_eq(line.to_array(), repeat(CHAR_DATA, 5))
|
||||
|
||||
|
||||
func test_shrink_to_0_length():
|
||||
line = BufferLineTest.new(10, CellData.from_char_data(CHAR_DATA), false)
|
||||
line.resize(0, CellData.from_char_data(CHAR_DATA))
|
||||
assert_eq(line.to_array(), repeat(CHAR_DATA, 0))
|
||||
|
||||
func shrink_then_enlarge():
|
||||
line = BufferLineTest.new(10, CellData.from_char_data(CHAR_DATA), false);
|
||||
line.set_cell(2, CellData.from_char_data([0, '😁', 1, '😁'.ord_at(0)]))
|
||||
line.set_cell(9, CellData.from_char_data([0, '😁', 1, '😁'.ord_at(0)]))
|
||||
assert_eq(line.translate_to_string(), 'aa😁aaaaaa😁')
|
||||
line.resize(5, CellData.from_char_data(CHAR_DATA))
|
||||
assert_eq(line.translate_to_string(), 'aa😁aa')
|
||||
line.resize(10, CellData.from_char_data(CHAR_DATA))
|
||||
assert_eq(line.translate_to_string(), 'aa😁aaaaaaa')
|
||||
|
||||
|
||||
class TestTrimLength:
|
||||
extends "res://addons/gut/test.gd"
|
||||
|
||||
|
||||
var line
|
||||
|
||||
|
||||
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]))
|
||||
|
||||
|
||||
func test_empty_line():
|
||||
assert_eq(line.get_trimmed_length(), 0)
|
||||
|
||||
|
||||
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)]))
|
||||
assert_eq(line.get_trimmed_length(), 3)
|
||||
|
||||
|
||||
func test_unicode():
|
||||
line.set_cell(0, CellData.from_char_data([1, "\u1f914", 1, "\u1f914".ord_at(0)]))
|
||||
line.set_cell(2, CellData.from_char_data([1, "\u1f914", 1, "\u1f914".ord_at(0)]))
|
||||
assert_eq(line.get_trimmed_length(), 3)
|
||||
|
||||
|
||||
func test_one_cell():
|
||||
line.set_cell(0, CellData.from_char_data([1, "a", 1, "a".ord_at(0)]))
|
||||
assert_eq(line.get_trimmed_length(), 1)
|
||||
|
||||
|
||||
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 TestTranslateToString:
|
||||
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), '')
|
|
@ -1,113 +0,0 @@
|
|||
# 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 Decoder = preload("res://addons/godot_xterm/input/text_decoder.gd")
|
||||
|
||||
# Note: There might be some invisible characters (such as emoji) depending
|
||||
# on your editor and font settings.
|
||||
const TEST_STRINGS = [
|
||||
"Лорем ипсум долор сит амет, ех сеа аццусам диссентиет. Ан еос стет еирмод витуперата. Иус дицерет урбанитас ет. Ан при алтера долорес сплендиде, цу яуо интегре денияуе, игнота волуптариа инструцтиор цу вим.",
|
||||
"ლორემ იფსუმ დოლორ სით ამეთ, ფაცერ მუციუს ცონსეთეთურ ყუო იდ, ფერ ვივენდუმ ყუაერენდუმ ეა, ესთ ამეთ მოვეთ სუავითათე ცუ. ვითაე სენსიბუს ან ვიხ. ეხერცი დეთერრუისსეთ უთ ყუი. ვოცენთ დებითის ადიფისცი ეთ ფერ. ნეც ან ფეუგაით ფორენსიბუს ინთერესსეთ. იდ დიცო რიდენს იუს. დისსენთიეთ ცონსეყუუნთურ სედ ნე, ნოვუმ მუნერე ეუმ ათ, ნე ეუმ ნიჰილ ირაცუნდია ურბანითას.",
|
||||
"अधिकांश अमितकुमार प्रोत्साहित मुख्य जाने प्रसारन विश्लेषण विश्व दारी अनुवादक अधिकांश नवंबर विषय गटकउसि गोपनीयता विकास जनित परस्पर गटकउसि अन्तरराष्ट्रीयकरन होसके मानव पुर्णता कम्प्युटर यन्त्रालय प्रति साधन",
|
||||
"覧六子当聞社計文護行情投身斗来。増落世的況上席備界先関権能万。本物挙歯乳全事携供板栃果以。頭月患端撤競見界記引去法条公泊候。決海備駆取品目芸方用朝示上用報。講申務紙約週堂出応理田流団幸稿。起保帯吉対阜庭支肯豪彰属本躍。量抑熊事府募動極都掲仮読岸。自続工就断庫指北速配鳴約事新住米信中験。婚浜袋著金市生交保他取情距。",
|
||||
"八メル務問へふらく博辞説いわょ読全タヨムケ東校どっ知壁テケ禁去フミ人過を装5階がねぜ法逆はじ端40落ミ予竹マヘナセ任1悪た。省ぜりせ製暇ょへそけ風井イ劣手はぼまず郵富法く作断タオイ取座ゅょが出作ホシ月給26島ツチ皇面ユトクイ暮犯リワナヤ断連こうでつ蔭柔薄とレにの。演めけふぱ損田転10得観びトげぎ王物鉄夜がまけ理惜くち牡提づ車惑参ヘカユモ長臓超漫ぼドかわ。",
|
||||
"모든 국민은 행위시의 법률에 의하여 범죄를 구성하지 아니하는 행위로 소추되지 아니하며. 전직대통령의 신분과 예우에 관하여는 법률로 정한다, 국회는 헌법 또는 법률에 특별한 규정이 없는 한 재적의원 과반수의 출석과 출석의원 과반수의 찬성으로 의결한다. 군인·군무원·경찰공무원 기타 법률이 정하는 자가 전투·훈련등 직무집행과 관련하여 받은 손해에 대하여는 법률이 정하는 보상외에 국가 또는 공공단체에 공무원의 직무상 불법행위로 인한 배상은 청구할 수 없다.",
|
||||
"كان فشكّل الشرقي مع, واحدة للمجهود تزامناً بعض بل. وتم جنوب للصين غينيا لم, ان وبدون وكسبت الأمور ذلك, أسر الخاسر الانجليزية هو. نفس لغزو مواقعها هو. الجو علاقة الصعداء انه أي, كما مع بمباركة للإتحاد الوزراء. ترتيب الأولى أن حدى, الشتوية باستحداث مدن بل, كان قد أوسع عملية. الأوضاع بالمطالبة كل قام, دون إذ شمال الربيع،. هُزم الخاصّة ٣٠ أما, مايو الصينية مع قبل.",
|
||||
"או סדר החול מיזמי קרימינולוגיה. קהילה בגרסה לויקיפדים אל היא, של צעד ציור ואלקטרוניקה. מדע מה ברית המזנון ארכיאולוגיה, אל טבלאות מבוקשים כלל. מאמרשיחהצפה העריכהגירסאות שכל אל, כתב עיצוב מושגי של. קבלו קלאסיים ב מתן. נבחרים אווירונאוטיקה אם מלא, לוח למנוע ארכיאולוגיה מה. ארץ לערוך בקרבת מונחונים או, עזרה רקטות לויקיפדים אחר גם.",
|
||||
"Лорем ლორემ अधिकांश 覧六子 八メル 모든 בקרבת äggg 123€ .",
|
||||
]
|
||||
|
||||
|
||||
func test_utf32_to_utf8():
|
||||
# 1 byte utf8 character
|
||||
assert_eq(
|
||||
Decoder.utf32_to_utf8(0x00000061),
|
||||
PoolByteArray([0x61])
|
||||
)
|
||||
# 2 byte utf8 character
|
||||
assert_eq(
|
||||
Decoder.utf32_to_utf8(0x00000761),
|
||||
PoolByteArray([0xdd, 0xa1])
|
||||
)
|
||||
# 3 byte utf8 character
|
||||
assert_eq(
|
||||
Decoder.utf32_to_utf8(0x00002621),
|
||||
PoolByteArray([0xe2, 0x98, 0xa1])
|
||||
)
|
||||
# 4 byte utf8 character
|
||||
assert_eq(
|
||||
Decoder.utf32_to_utf8(0x00010144),
|
||||
PoolByteArray([0xf0, 0x90, 0x85, 0x84])
|
||||
)
|
||||
assert_eq(
|
||||
Decoder.utf32_to_utf8(0x0001f427) as Array,
|
||||
PoolByteArray([0xf0, 0x9f, 0x90, 0xa7]) as Array
|
||||
)
|
||||
|
||||
|
||||
func test_utf32_to_string():
|
||||
assert_eq(
|
||||
Decoder.utf32_to_string([49, 50, 51, 0x1d11e, 49, 50, 51]),
|
||||
'123𝄞123'
|
||||
)
|
||||
|
||||
class TestUtf8ToUtf32Decoder:
|
||||
extends 'res://addons/gut/test.gd'
|
||||
|
||||
var decoder = Decoder.Utf8ToUtf32.new()
|
||||
var target = []
|
||||
|
||||
# Full codepoint tests take a long time to run, so skip them unless this
|
||||
# environment variable is set.
|
||||
var skip_full_codepoint_tests = not OS.get_environment("RUN_FULL_CODEPOINT_TESTS")
|
||||
|
||||
|
||||
func before_each():
|
||||
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
|
||||
if skip_full_codepoint_tests:
|
||||
print("Skipping full codepoint test")
|
||||
return
|
||||
for i in range(65536):
|
||||
# skip surrogate pairs
|
||||
if i >= 0xD800 and i <= 0xDFFF:
|
||||
continue
|
||||
# FIXME: Skip 0xfeff (zero width no-break space)
|
||||
# which fails for some reason
|
||||
if i == 0xfeff:
|
||||
continue
|
||||
var utf8_data = Decoder.utf32_to_utf8(i)
|
||||
var length = decoder.decode(utf8_data, target)
|
||||
assert_eq(length, 1)
|
||||
assert_eq(char(target[0]), utf8_data.get_string_from_utf8(),
|
||||
"Wrong string for codepoint 0x%x" % target[0])
|
||||
decoder.clear()
|
||||
|
||||
func test_full_codepoint_65536_to_0x10FFFF(): # 4 byte sequences
|
||||
if skip_full_codepoint_tests:
|
||||
print("Skipping full codepoint test")
|
||||
return
|
||||
for i in range(65536, 0x10FFFF):
|
||||
var utf8_data = Decoder.utf32_to_utf8(i)
|
||||
var length = decoder.decode(utf8_data, target)
|
||||
assert_eq(length, 1)
|
||||
assert_eq(target[0], i)
|
||||
|
||||
func test_test_strings():
|
||||
target.resize(500)
|
||||
for string in TEST_STRINGS:
|
||||
var utf8_data = string.to_utf8()
|
||||
var length = decoder.decode(utf8_data, target)
|
||||
assert_eq(Decoder.utf32_to_string(target, 0, length), string)
|
||||
decoder.clear()
|
|
@ -1,100 +0,0 @@
|
|||
# Copyright (c) 2020 The GodotXterm authors.
|
||||
# Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
# License MIT
|
||||
extends "res://addons/gut/test.gd"
|
||||
|
||||
const DcsParser = preload("res://addons/godot_xterm/parser/dcs_parser.gd")
|
||||
const Parser = preload("res://addons/godot_xterm/parser/escape_sequence_parser.gd")
|
||||
const Params = preload("res://addons/godot_xterm/parser/params.gd")
|
||||
const Decoder = preload("res://addons/godot_xterm/input/text_decoder.gd")
|
||||
|
||||
class Handler:
|
||||
extends Reference
|
||||
|
||||
|
||||
var _output
|
||||
var _msg
|
||||
var _return_false
|
||||
|
||||
|
||||
func _init(output: Array, msg: String, return_false: bool = false):
|
||||
_output = output
|
||||
_msg = msg
|
||||
_return_false = return_false
|
||||
|
||||
|
||||
func hook(params):
|
||||
_output.append([_msg, 'HOOK', params.to_array()])
|
||||
|
||||
|
||||
func put(data: Array, start: int, end: int):
|
||||
_output.append([_msg, 'PUT', Decoder.utf32_to_string(data, start, end)])
|
||||
|
||||
|
||||
func unhook(success: bool):
|
||||
_output.append([_msg, 'UNHOOK', success])
|
||||
if _return_false:
|
||||
return false
|
||||
|
||||
|
||||
var parser: DcsParser
|
||||
var reports: Array
|
||||
|
||||
|
||||
func to_utf32(s: String):
|
||||
var utf32 = []
|
||||
utf32.resize(s.length())
|
||||
var decoder = Decoder.Utf8ToUtf32.new()
|
||||
var length = decoder.decode(s.to_utf8(), utf32)
|
||||
assert_eq(length, s.length())
|
||||
return utf32.slice(0, length - 1)
|
||||
|
||||
|
||||
func handler_fallback(id, action, data):
|
||||
if action == 'HOOK':
|
||||
data = data.to_array()
|
||||
reports.append([id, action, data])
|
||||
|
||||
|
||||
func before_each():
|
||||
parser = DcsParser.new()
|
||||
parser.set_handler_fallback(self, 'handler_fallback')
|
||||
reports = []
|
||||
|
||||
|
||||
func test_set_dcs_handler():
|
||||
parser.set_handler(Parser.identifier({'intermediates': '+', 'final': 'p'}),
|
||||
Handler.new(reports, 'th'))
|
||||
parser.hook(Parser.identifier({'intermediates': '+', 'final': 'p'}),
|
||||
Params.from_array([1, 2, 3]))
|
||||
var data = to_utf32('Here comes')
|
||||
parser.put(data, 0, data.size())
|
||||
data = to_utf32('the mouse!')
|
||||
parser.put(data, 0, data.size())
|
||||
parser.unhook(true)
|
||||
assert_eq(reports, [
|
||||
# messages from Handler
|
||||
['th', 'HOOK', [1, 2, 3]],
|
||||
['th', 'PUT', 'Here comes'],
|
||||
['th', 'PUT', 'the mouse!'],
|
||||
['th', 'UNHOOK', true],
|
||||
])
|
||||
|
||||
|
||||
func test_clear_dcs_handler():
|
||||
var ident = Parser.identifier({'intermediates': '+', 'final': 'p'})
|
||||
parser.set_handler(ident, Handler.new(reports, 'th'))
|
||||
parser.clear_handler(ident)
|
||||
parser.hook(ident, Params.from_array([1, 2, 3]))
|
||||
var data = to_utf32('Here comes')
|
||||
parser.put(data, 0, data.size())
|
||||
data = to_utf32('the mouse!')
|
||||
parser.put(data, 0, data.size())
|
||||
parser.unhook(true)
|
||||
assert_eq(reports, [
|
||||
# messages from fallback handler
|
||||
[ident, 'HOOK', [1, 2, 3]],
|
||||
[ident, 'PUT', 'Here comes'],
|
||||
[ident, 'PUT', 'the mouse!'],
|
||||
[ident, 'UNHOOK', true],
|
||||
])
|
|
@ -1,411 +0,0 @@
|
|||
# Copyright (c) 2020 The GodotXterm authors.
|
||||
# Copyright (c) 2018 The xterm.js authors. All rights reserved.
|
||||
# License MIT
|
||||
extends 'res://addons/gut/test.gd'
|
||||
|
||||
const Parser = preload("res://addons/godot_xterm/parser/escape_sequence_parser.gd")
|
||||
const Params = preload("res://addons/godot_xterm/parser/params.gd")
|
||||
const Decoder = preload("res://addons/godot_xterm/input/text_decoder.gd")
|
||||
const Constants = preload("res://addons/godot_xterm/parser/constants.gd")
|
||||
const ParserState = Constants.ParserState
|
||||
|
||||
class TestTerminal:
|
||||
var calls = []
|
||||
|
||||
func clear():
|
||||
calls = []
|
||||
|
||||
|
||||
func handle_print(data, start, end):
|
||||
var string = Decoder.utf32_to_string(data, start, end)
|
||||
calls.append(['print', string])
|
||||
|
||||
|
||||
func handle_csi(ident, params):
|
||||
var id = Parser.ident_to_string(ident)
|
||||
var collect = id.substr(0, id.length() - 1)
|
||||
var flag = id.substr(id.length() - 1, 1)
|
||||
calls.append(['csi', collect, params, flag])
|
||||
|
||||
|
||||
func handle_esc(ident: int):
|
||||
var id = Parser.ident_to_string(ident)
|
||||
var collect = id.substr(0, id.length() - 1)
|
||||
var flag = id.substr(id.length() - 1, 1)
|
||||
calls.append(['esc', collect, flag])
|
||||
|
||||
|
||||
func handle_execute(code: int):
|
||||
var flag = char(code)
|
||||
calls.append(['exe', flag])
|
||||
|
||||
|
||||
func handle_dcs(collect_and_flag, action, payload):
|
||||
match action:
|
||||
'HOOK':
|
||||
calls.append(['dcs hook', payload.to_array()])
|
||||
'PUT':
|
||||
calls.append(['dcs put', payload])
|
||||
'UNHOOK':
|
||||
calls.append(['dcs unhook', payload])
|
||||
|
||||
|
||||
# derived parser with access to internal states
|
||||
class TestParser:
|
||||
extends Parser
|
||||
|
||||
var params setget _set_params,_get_params
|
||||
var collect setget _set_collect,_get_collect
|
||||
|
||||
|
||||
func _init():
|
||||
pass
|
||||
|
||||
|
||||
func _set_params(value):
|
||||
_params = Params.from_array(value)
|
||||
|
||||
|
||||
func _get_params():
|
||||
return _params.to_array()
|
||||
|
||||
|
||||
func _set_collect(value: String):
|
||||
_collect = 0
|
||||
for c in value.to_ascii():
|
||||
_collect <<= 8
|
||||
_collect |= c
|
||||
|
||||
|
||||
func _get_collect() -> String:
|
||||
return ident_to_string(_collect)
|
||||
|
||||
|
||||
func real_params():
|
||||
return _params
|
||||
|
||||
# translate string based parse calls into typed array based
|
||||
func parse(parser: TestParser, data):
|
||||
if data == '': # handle the 0x00 codepoint
|
||||
data = PoolByteArray([0])
|
||||
else:
|
||||
data = data.to_utf8()
|
||||
var container = []
|
||||
var decoder = Decoder.Utf8ToUtf32.new()
|
||||
decoder.clear()
|
||||
var length = decoder.decode(data, container)
|
||||
parser.parse(container, length)
|
||||
|
||||
|
||||
var parser
|
||||
var test_terminal
|
||||
|
||||
|
||||
func before_all():
|
||||
parser = TestParser.new()
|
||||
test_terminal = TestTerminal.new()
|
||||
|
||||
parser.set_print_handler(test_terminal, 'handle_print')
|
||||
parser.set_csi_handler_fallback(test_terminal, 'handle_csi')
|
||||
parser.set_esc_handler_fallback(test_terminal, 'handle_esc')
|
||||
parser.set_execute_handler_fallback(test_terminal, "handle_execute")
|
||||
parser.set_dcs_handler_fallback(test_terminal, "handle_dcs")
|
||||
|
||||
|
||||
func before_each():
|
||||
parser.reset()
|
||||
test_terminal.clear()
|
||||
|
||||
|
||||
func test_initial_states():
|
||||
assert_eq(parser.initial_state, ParserState.GROUND)
|
||||
assert_eq(parser.current_state, ParserState.GROUND)
|
||||
assert_eq(parser._params.to_array(), [0])
|
||||
|
||||
func test_reset_states():
|
||||
var params = Params.new()
|
||||
params.add_param(123)
|
||||
parser.current_state = 124
|
||||
parser._params = params
|
||||
parser.reset()
|
||||
assert_eq(parser.current_state, ParserState.GROUND)
|
||||
assert_eq(parser._params.to_array(), [0])
|
||||
|
||||
# state transitions and actions
|
||||
|
||||
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, 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 = char(printable)
|
||||
parser.current_state = ParserState.GROUND
|
||||
parse(parser, string)
|
||||
assert_eq(parser.current_state, ParserState.GROUND)
|
||||
assert_eq(test_terminal.calls, [['print', string]])
|
||||
parser.reset()
|
||||
test_terminal.clear()
|
||||
|
||||
func test_trans_ANYWHERE_to_GROUND_with_actions():
|
||||
var exes = [
|
||||
'\u0018', '\u001a',
|
||||
'\u0080', '\u0081', '\u0082', '\u0083', '\u0084', '\u0085', '\u0086', '\u0087', '\u0088',
|
||||
'\u0089', '\u008a', '\u008b', '\u008c', '\u008d', '\u008e', '\u008f',
|
||||
'\u0091', '\u0092', '\u0093', '\u0094', '\u0095', '\u0096', '\u0097', '\u0099', '\u009a'
|
||||
]
|
||||
var exceptions = {
|
||||
8: { '\u0018': [], '\u001a': [] }, # abort OSC_STRING
|
||||
13: { '\u0018': [['dcs unhook', false]], '\u001a': [['dcs unhook', false]] } # abort DCS_PASSTHROUGH
|
||||
}
|
||||
for state in ParserState.values():
|
||||
for exe in exes:
|
||||
if exe != '\u0018' and exe != '\u001a':
|
||||
continue
|
||||
parser.current_state = state
|
||||
parse(parser, exe)
|
||||
assert_eq(parser.current_state, ParserState.GROUND)
|
||||
assert_eq(
|
||||
test_terminal.calls,
|
||||
exceptions[state][exe] if exceptions.has(state) and exceptions[state].has(exe) else [['exe', exe]],
|
||||
'state: %s exe: %x' % [ParserState.keys()[state], exe.to_utf8()[0]]
|
||||
)
|
||||
parser.reset()
|
||||
test_terminal.clear()
|
||||
parse(parser, '\u009c')
|
||||
assert_eq(parser.current_state, ParserState.GROUND)
|
||||
assert_eq(test_terminal.calls, [])
|
||||
parser.reset()
|
||||
test_terminal.clear()
|
||||
|
||||
|
||||
func skip_test_trans_ANYWHERE_to_ESCAPE_with_clear():
|
||||
for state in ParserState.values():
|
||||
var state_name = ParserState.keys()[state]
|
||||
parser.current_state = state
|
||||
parser.params = [23]
|
||||
parser.collect = '#'
|
||||
parse(parser, '\u001b')
|
||||
assert_eq(parser.current_state, ParserState.ESCAPE,
|
||||
'wrong current_state. start state: %s' % state_name)
|
||||
assert_eq(parser.params, [0],
|
||||
'wrong params. start state: %s' % state_name)
|
||||
assert_eq(parser.collect, '',
|
||||
'wrong collect. start state: %s' % state_name)
|
||||
parser.reset()
|
||||
|
||||
|
||||
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 = 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)
|
||||
parser.reset()
|
||||
test_terminal.clear()
|
||||
|
||||
|
||||
func test_state_ESCAPE_ignore():
|
||||
parser.current_state = ParserState.ESCAPE
|
||||
parse(parser, '\u007f')
|
||||
assert_eq(parser.current_state, ParserState.ESCAPE)
|
||||
assert_eq(test_terminal.calls, [])
|
||||
|
||||
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 = char(dispatch)
|
||||
parse(parser, data)
|
||||
assert_eq(parser.current_state, ParserState.GROUND,
|
||||
'wrong state: %s, dispatch: %x' % [ParserState.keys()[parser.current_state], dispatch])
|
||||
assert_eq(test_terminal.calls, [['esc', '', data]],
|
||||
'wrong call. dispatch: %x' % dispatch)
|
||||
parser.reset()
|
||||
test_terminal.clear()
|
||||
|
||||
|
||||
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 = char(c)
|
||||
parse(parser, data)
|
||||
assert_eq(parser.current_state, ParserState.ESCAPE_INTERMEDIATE)
|
||||
assert_eq(parser.collect, data)
|
||||
parser.reset()
|
||||
|
||||
|
||||
func test_state_ESCAPE_INTERMEDIATE_execute_rules():
|
||||
var exes = range(0x00, 0x18) + [0x19] + range(0x1c, 0x20)
|
||||
for exe in exes:
|
||||
var data = char(exe)
|
||||
parser.current_state = ParserState.ESCAPE_INTERMEDIATE
|
||||
parse(parser, data)
|
||||
assert_eq(parser.current_state, ParserState.ESCAPE_INTERMEDIATE)
|
||||
assert_eq(test_terminal.calls, [['exe', data]])
|
||||
parser.reset()
|
||||
test_terminal.clear()
|
||||
|
||||
|
||||
func test_state_ESCAPE_INTERMEDIATE_ignore():
|
||||
parser.current_state = ParserState.ESCAPE_INTERMEDIATE
|
||||
parse(parser, '\u007f')
|
||||
assert_eq(parser.current_state, ParserState.ESCAPE_INTERMEDIATE)
|
||||
assert_eq(test_terminal.calls, [])
|
||||
|
||||
|
||||
func test_state_ESCAPE_INTERMEDIATE_collect_action():
|
||||
var collect = range(0x20, 0x30)
|
||||
for c in collect:
|
||||
var data = char(c)
|
||||
parser.current_state = ParserState.ESCAPE_INTERMEDIATE
|
||||
parse(parser, data)
|
||||
assert_eq(parser.current_state, ParserState.ESCAPE_INTERMEDIATE)
|
||||
assert_eq(parser.collect, data)
|
||||
parser.reset()
|
||||
|
||||
|
||||
func test_trans_ESCAPE_INTERMEDIATE_to_GROUND_with_esc_dispatch_action():
|
||||
var collect = range(0x30, 0x7f)
|
||||
for c in collect:
|
||||
var data = char(c)
|
||||
parser.current_state = ParserState.ESCAPE_INTERMEDIATE
|
||||
parse(parser, data)
|
||||
assert_eq(parser.current_state, ParserState.GROUND)
|
||||
# '\u005c' --> ESC + \ (7bit ST) parser does not expose this as it already got handled
|
||||
assert_eq(test_terminal.calls, [] if c == 0x5c else [['esc', '', data]], 'c: 0x%x' % c)
|
||||
parser.reset()
|
||||
test_terminal.clear()
|
||||
|
||||
func test_ANYWHERE_or_ESCAPE_to_CSI_ENTRY_with_clear():
|
||||
# C0
|
||||
parser.current_state = ParserState.ESCAPE
|
||||
parser.params = [123]
|
||||
parser.collect = '#'
|
||||
parse(parser, '[')
|
||||
assert_eq(parser.current_state, ParserState.CSI_ENTRY)
|
||||
assert_eq(parser.params, [0])
|
||||
assert_eq(parser.collect, '')
|
||||
parser.reset()
|
||||
# C1
|
||||
for state in ParserState.values():
|
||||
parser.current_state = state
|
||||
parser.params = [123]
|
||||
parser.collect = '#'
|
||||
parse(parser, '\u009b')
|
||||
assert_eq(parser.current_state, ParserState.CSI_ENTRY)
|
||||
assert_eq(parser.collect, '')
|
||||
parser.reset()
|
||||
|
||||
|
||||
func test_CSI_ENTRY_execute_rules():
|
||||
var exes = range(0x00, 0x18) + [0x19] + range(0x1c, 0x20)
|
||||
for exe in exes:
|
||||
var data = char(exe)
|
||||
parser.current_state = ParserState.CSI_ENTRY
|
||||
parse(parser, data)
|
||||
assert_eq(parser.current_state, ParserState.CSI_ENTRY)
|
||||
assert_eq(test_terminal.calls, [['exe', data]])
|
||||
parser.reset()
|
||||
test_terminal.clear()
|
||||
|
||||
|
||||
func test_state_CSI_ENTRY_ignore():
|
||||
parser.current_state = ParserState.CSI_ENTRY
|
||||
parse(parser, '\u007f')
|
||||
assert_eq(parser.current_state, ParserState.CSI_ENTRY)
|
||||
assert_eq(test_terminal.calls, [])
|
||||
|
||||
|
||||
func test_trans_CSI_ENTRY_to_GROUND_with_csi_dispatch_action():
|
||||
var dispatches = range(0x40, 0x7f)
|
||||
for dispatch in dispatches:
|
||||
var data = char(dispatch)
|
||||
parser.current_state = ParserState.CSI_ENTRY
|
||||
parse(parser, data)
|
||||
assert_eq(parser.current_state, ParserState.GROUND)
|
||||
assert_eq(test_terminal.calls, [['csi', '', [0], data]])
|
||||
parser.reset()
|
||||
test_terminal.clear()
|
||||
|
||||
|
||||
func test_trans_CSI_ENTRY_to_CSI_PARAMS_with_param_or_collect_action():
|
||||
var params = range(0x30, 0x3a)
|
||||
var collect = ['\u003c', '\u003d', '\u003e', '\u003f']
|
||||
for param in params:
|
||||
parser.current_state = ParserState.CSI_ENTRY
|
||||
parse(parser, char(param))
|
||||
assert_eq(parser.current_state, ParserState.CSI_PARAM)
|
||||
assert_eq(parser.params, [param - 48], 'param: 0x%x' % param)
|
||||
parser.reset()
|
||||
parser.current_state = ParserState.CSI_ENTRY
|
||||
parse(parser, '\u003b')
|
||||
assert_eq(parser.current_state, ParserState.CSI_PARAM)
|
||||
assert_eq(parser.params, [0, 0])
|
||||
parser.reset()
|
||||
for c in collect:
|
||||
parser.current_state = ParserState.CSI_ENTRY
|
||||
parse(parser, c)
|
||||
assert_eq(parser.current_state, ParserState.CSI_PARAM)
|
||||
assert_eq(parser.collect, c)
|
||||
parser.reset()
|
||||
|
||||
|
||||
func test_state_CSI_PARAM_execute_rules():
|
||||
var exes = range(0x00, 0x018) + [0x19] + range(0x1c, 0x20)
|
||||
for exe in exes:
|
||||
var data = char(exe)
|
||||
parser.current_state = ParserState.CSI_PARAM
|
||||
parse(parser, data)
|
||||
assert_eq(parser.current_state, ParserState.CSI_PARAM)
|
||||
assert_eq(test_terminal.calls, [['exe', data]])
|
||||
parser.reset()
|
||||
test_terminal.clear()
|
||||
|
||||
|
||||
func test_state_CSI_PARAM_param_action():
|
||||
var params = range(0x30, 0x3a)
|
||||
for param in params:
|
||||
parser.current_state = ParserState.CSI_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()
|
||||
|
||||
|
||||
func test_state_CSI_PARAM_ignore():
|
||||
parser.current_state = ParserState.CSI_PARAM
|
||||
parse(parser, '\u007f')
|
||||
assert_eq(parser.current_state, ParserState.CSI_PARAM)
|
||||
assert_eq(test_terminal.calls, [])
|
||||
|
||||
|
||||
func test_trans_CSI_PARAM_to_GROUND_with_csi_dispatch_action():
|
||||
var dispatches = range(0x40, 0x7f)
|
||||
for dispatch in dispatches:
|
||||
var data = char(dispatch)
|
||||
parser.current_state = ParserState.CSI_PARAM
|
||||
parser.params = [0, 1]
|
||||
parse(parser, data)
|
||||
assert_eq(parser.current_state, ParserState.GROUND)
|
||||
assert_eq(test_terminal.calls, [['csi', '', [0, 1], data]])
|
||||
parser.reset()
|
||||
test_terminal.clear()
|
||||
|
||||
|
||||
func test_trans_CSI_ENTRY_to_CSI_INTERMEDIATE_with_collect_action():
|
||||
for collect in range(0x20, 0x30):
|
||||
var data = char(collect)
|
||||
parser.current_state = ParserState.CSI_ENTRY
|
||||
parse(parser, data)
|
||||
assert_eq(parser.current_state, ParserState.CSI_INTERMEDIATE)
|
||||
assert_eq(parser.collect, data)
|
||||
parser.reset()
|
|
@ -1,202 +0,0 @@
|
|||
# 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]])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
# 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)
|
|
@ -1,38 +0,0 @@
|
|||
# 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), [])
|
|
@ -1,201 +0,0 @@
|
|||
# Copyright (c) 2016 The xterm.js authors. All rights reserved.
|
||||
# Ported to GDScript by the GodotXterm authors.
|
||||
# License MIT
|
||||
extends "res://addons/gut/test.gd"
|
||||
|
||||
|
||||
const CIRCULAR_LIST_PATH = "res://addons/godot_xterm/circular_list.gd"
|
||||
const CircularList = preload(CIRCULAR_LIST_PATH)
|
||||
|
||||
var list
|
||||
|
||||
|
||||
func before_each():
|
||||
list = CircularList.new(5)
|
||||
|
||||
|
||||
func test_push():
|
||||
list.push("1")
|
||||
list.push("2")
|
||||
list.push("3")
|
||||
list.push("4")
|
||||
list.push("5")
|
||||
assert_eq(list.get_line(0), "1")
|
||||
assert_eq(list.get_line(1), "2")
|
||||
assert_eq(list.get_line(2), "3")
|
||||
assert_eq(list.get_line(3), "4")
|
||||
assert_eq(list.get_line(4), "5")
|
||||
|
||||
|
||||
func test_splice_deletes_items():
|
||||
list = CircularList.new(2)
|
||||
list.push("1")
|
||||
list.push("2")
|
||||
list.splice(0, 1)
|
||||
assert_eq(list.length, 1)
|
||||
assert_eq(list.get_el(0), "2")
|
||||
list.push("3")
|
||||
list.splice(1, 1)
|
||||
assert_eq(list.length, 1)
|
||||
assert_eq(list.get_el(0), "2")
|
||||
|
||||
|
||||
func test_splice_inserts_items():
|
||||
list = CircularList.new(2)
|
||||
list.push("1")
|
||||
list.splice(0, 0, ["2"])
|
||||
assert_eq(list.length, 2)
|
||||
assert_eq(list.get_el(0), "2")
|
||||
assert_eq(list.get_el(1), "1")
|
||||
list.splice(1, 0, ["3"])
|
||||
assert_eq(list.length, 2)
|
||||
assert_eq(list.get_el(0), "3")
|
||||
assert_eq(list.get_el(1), "1")
|
||||
|
||||
|
||||
func test_splice_deletes_items_then_inserts_items():
|
||||
list = CircularList.new(3)
|
||||
list.push("1")
|
||||
list.push("2")
|
||||
list.splice(0, 1, ["3", "4"])
|
||||
assert_eq(list.length, 3)
|
||||
assert_eq(list.get_el(0), "3")
|
||||
assert_eq(list.get_el(1), "4")
|
||||
assert_eq(list.get_el(2), "2")
|
||||
|
||||
|
||||
func test_splice_wraps_the_array_correctly_when_more_items_are_inserted_than_deleted():
|
||||
list = CircularList.new(3)
|
||||
list.push("1")
|
||||
list.push("2")
|
||||
list.splice(1, 0, ["3", "4"])
|
||||
assert_eq(list.length, 3)
|
||||
assert_eq(list.get_el(0), "3")
|
||||
assert_eq(list.get_el(1), "4")
|
||||
assert_eq(list.get_el(2), "2")
|
||||
|
||||
|
||||
class TestShiftElements:
|
||||
extends "res://addons/gut/test.gd"
|
||||
|
||||
|
||||
var list
|
||||
|
||||
|
||||
func before_each():
|
||||
list = CircularList.new(5)
|
||||
|
||||
|
||||
func test_does_not_mutate_the_list_when_count_is_0():
|
||||
list.push(1)
|
||||
list.push(2)
|
||||
list.shift_elements(0, 0, 1)
|
||||
assert_eq(list.length, 2)
|
||||
assert_eq(list.get_el(0), 1)
|
||||
assert_eq(list.get_el(1), 2)
|
||||
|
||||
|
||||
func test_pushes_errors_for_invalid_args():
|
||||
list = partial_double(CIRCULAR_LIST_PATH).new()
|
||||
list.max_length = 5
|
||||
list.push(1)
|
||||
list.shift_elements(-1, 1, 1)
|
||||
assert_called(list, "push_error", ["start argument out of range"])
|
||||
list.shift_elements(1, 1, 1)
|
||||
assert_called(list, "push_error", ["start argument out of range"])
|
||||
list.shift_elements(0, 1, -1)
|
||||
assert_called(list, "push_error", ["cannot shift elements in list beyond index 0"])
|
||||
|
||||
|
||||
func test_trim_start_removes_items_from_the_beginning_of_the_list():
|
||||
list.push("1")
|
||||
list.push("2")
|
||||
list.push("3")
|
||||
list.push("4")
|
||||
list.push("5")
|
||||
list.trim_start(1)
|
||||
assert_eq(list.length, 4)
|
||||
assert_eq(list.get_el(0), "2")
|
||||
assert_eq(list.get_el(1), "3")
|
||||
assert_eq(list.get_el(2), "4")
|
||||
assert_eq(list.get_el(3), "5")
|
||||
list.trim_start(2)
|
||||
assert_eq(list.length, 2)
|
||||
assert_eq(list.get_el(0), "4")
|
||||
assert_eq(list.get_el(1), "5")
|
||||
|
||||
|
||||
func test_trim_start_removes_all_items_if_the_requested_trim_amount_is_larger_than_the_lists_length():
|
||||
list.push("1")
|
||||
list.trim_start(2)
|
||||
assert_eq(list.length, 0)
|
||||
|
||||
|
||||
func test_shifts_an_element_forward():
|
||||
list.push(1)
|
||||
list.push(2)
|
||||
list.shift_elements(0, 1, 1)
|
||||
assert_eq(list.length, 2)
|
||||
assert_eq(list.get_el(0), 1)
|
||||
assert_eq(list.get_el(1), 1)
|
||||
|
||||
|
||||
func test_shifts_elements_forward():
|
||||
list.push(1)
|
||||
list.push(2)
|
||||
list.push(3)
|
||||
list.push(4)
|
||||
list.shift_elements(0, 2, 2)
|
||||
assert_eq(list.length, 4)
|
||||
assert_eq(list.get_el(0), 1)
|
||||
assert_eq(list.get_el(1), 2)
|
||||
assert_eq(list.get_el(2), 1)
|
||||
assert_eq(list.get_el(3), 2)
|
||||
|
||||
|
||||
func test_shifts_elements_forward_expanding_the_list_if_needed():
|
||||
list.push(1)
|
||||
list.push(2)
|
||||
list.shift_elements(0, 2, 2)
|
||||
assert_eq(list.length, 4)
|
||||
assert_eq(list.get_el(0), 1)
|
||||
assert_eq(list.get_el(1), 2)
|
||||
assert_eq(list.get_el(2), 1)
|
||||
assert_eq(list.get_el(3), 2)
|
||||
|
||||
|
||||
func test_shifts_elements_forward_wrapping_the_list_if_needed():
|
||||
list.push(1)
|
||||
list.push(2)
|
||||
list.push(3)
|
||||
list.push(4)
|
||||
list.push(5)
|
||||
list.shift_elements(2, 2, 3)
|
||||
assert_eq(list.length, 5)
|
||||
assert_eq(list.get_el(0), 3)
|
||||
assert_eq(list.get_el(1), 4)
|
||||
assert_eq(list.get_el(2), 5)
|
||||
assert_eq(list.get_el(3), 3)
|
||||
assert_eq(list.get_el(4), 4)
|
||||
|
||||
|
||||
func test_shifts_an_element_backwards():
|
||||
list.push(1)
|
||||
list.push(2)
|
||||
list.shift_elements(1, 1, -1)
|
||||
assert_eq(list.length, 2)
|
||||
assert_eq(list.get_el(0), 2)
|
||||
assert_eq(list.get_el(1), 2)
|
||||
|
||||
|
||||
func test_shiftS_elements_backwards():
|
||||
list.push(1)
|
||||
list.push(2)
|
||||
list.push(3)
|
||||
list.push(4)
|
||||
list.shift_elements(2, 2, -2)
|
||||
assert_eq(list.length, 4)
|
||||
assert_eq(list.get_el(0), 3)
|
||||
assert_eq(list.get_el(1), 4)
|
||||
assert_eq(list.get_el(2), 3)
|
||||
assert_eq(list.get_el(3), 4)
|
|
@ -1,288 +0,0 @@
|
|||
# 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")
|
||||
const Constants = preload("res://addons/godot_xterm/buffer/constants.gd")
|
||||
const OptionsService = preload("res://addons/godot_xterm/services/options_service.gd")
|
||||
|
||||
const CursorStyle = Constants.CursorStyle
|
||||
|
||||
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)
|
||||
|
||||
|
||||
func test_save_and_restore_cursor():
|
||||
buffer_service.buffer.x = 1
|
||||
buffer_service.buffer.y = 2
|
||||
buffer_service.buffer.ybase = 0
|
||||
input_handler._cur_attr_data.fg = 3
|
||||
# Save cursor position
|
||||
input_handler.save_cursor()
|
||||
assert_eq(buffer_service.buffer.x, 1)
|
||||
assert_eq(buffer_service.buffer.y, 2)
|
||||
assert_eq(input_handler._cur_attr_data.fg, 3)
|
||||
# Change the cursor position
|
||||
buffer_service.buffer.x = 10
|
||||
buffer_service.buffer.y = 20
|
||||
input_handler._cur_attr_data.fg = 30
|
||||
# Restore cursor position
|
||||
input_handler.restore_cursor()
|
||||
assert_eq(buffer_service.buffer.x, 1)
|
||||
assert_eq(buffer_service.buffer.y, 2)
|
||||
assert_eq(input_handler._cur_attr_data.fg, 3)
|
||||
|
||||
|
||||
func test_set_cursor_style():
|
||||
input_handler.set_cursor_style(Params.from_array([0]))
|
||||
assert_eq(options_service.options.cursor_style, CursorStyle.BLOCK)
|
||||
assert_eq(options_service.options.cursor_blink, true)
|
||||
|
||||
options_service.options = OptionsService.TerminalOptions.new()
|
||||
input_handler.set_cursor_style(Params.from_array([1]))
|
||||
assert_eq(options_service.options.cursor_style, CursorStyle.BLOCK)
|
||||
assert_eq(options_service.options.cursor_blink, true)
|
||||
|
||||
options_service.options = OptionsService.TerminalOptions.new()
|
||||
input_handler.set_cursor_style(Params.from_array([2]))
|
||||
assert_eq(options_service.options.cursor_style, CursorStyle.BLOCK)
|
||||
assert_eq(options_service.options.cursor_blink, false)
|
||||
|
||||
options_service.options = OptionsService.TerminalOptions.new()
|
||||
input_handler.set_cursor_style(Params.from_array([3]))
|
||||
assert_eq(options_service.options.cursor_style, CursorStyle.UNDERLINE)
|
||||
assert_eq(options_service.options.cursor_blink, true)
|
||||
|
||||
options_service.options = OptionsService.TerminalOptions.new()
|
||||
input_handler.set_cursor_style(Params.from_array([4]))
|
||||
assert_eq(options_service.options.cursor_style, CursorStyle.UNDERLINE)
|
||||
assert_eq(options_service.options.cursor_blink, false)
|
||||
|
||||
options_service.options = OptionsService.TerminalOptions.new()
|
||||
input_handler.set_cursor_style(Params.from_array([5]))
|
||||
assert_eq(options_service.options.cursor_style, CursorStyle.BAR)
|
||||
assert_eq(options_service.options.cursor_blink, true)
|
||||
|
||||
options_service.options = OptionsService.TerminalOptions.new()
|
||||
input_handler.set_cursor_style(Params.from_array([6]))
|
||||
assert_eq(options_service.options.cursor_style, CursorStyle.BAR)
|
||||
assert_eq(options_service.options.cursor_blink, false)
|
||||
|
||||
|
||||
func test_set_mode_toggles_bracketed_paste_mode():
|
||||
# Set bracketed paste mode
|
||||
input_handler.set_mode_private(Params.from_array([2004]))
|
||||
assert_true(core_service.dec_private_modes.bracketed_paste_mode)
|
||||
# Reset bracketed paste mode
|
||||
input_handler.reset_mode_private(Params.from_array([2004]))
|
||||
assert_false(core_service.dec_private_modes.bracketed_paste_mode)
|
||||
|
||||
|
||||
func test_erase_in_line():
|
||||
buffer_service = TestUtils.MockBufferService.new(80, 30, 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 = 70
|
||||
input_handler.erase_in_line(Params.from_array([0]))
|
||||
assert_eq(buffer_service.buffer.lines.get_line(0).translate_to_string(false),
|
||||
repeat("a", 70) + " ")
|
||||
|
||||
# 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_line(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_line(2).translate_to_string(false),
|
||||
repeat(" ", buffer_service.cols))
|
||||
|
||||
|
||||
func 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(repeat("a", buffer_service.cols)) # line 0
|
||||
input_handler.parse(repeat("a", buffer_service.cols + 9)) # line 1 and 2
|
||||
for i in range(3, buffer_service.rows):
|
||||
input_handler.parse(repeat("a", buffer_service.cols))
|
||||
|
||||
# params[1] left and above with wrap
|
||||
# confirm precondition that line 2 is wrapped
|
||||
assert_true(buffer_service.buffer.lines.get_line(2).is_wrapped)
|
||||
buffer_service.buffer.y = 2
|
||||
buffer_service.buffer.x = 40
|
||||
input_handler.erase_in_display(Params.from_array([1]))
|
||||
assert_false(buffer_service.buffer.lines.get_line(2).is_wrapped)
|
||||
|
||||
# reset and add a wrapped line
|
||||
buffer_service.buffer.y = 0
|
||||
buffer_service.buffer.x = 0
|
||||
input_handler.parse(repeat("a", buffer_service.cols)) # line 0
|
||||
input_handler.parse(repeat("a", buffer_service.cols + 9)) # line 1 and 2
|
||||
for i in range(3, buffer_service.rows):
|
||||
input_handler.parse(repeat("a", buffer_service.cols))
|
||||
|
||||
# params[1] left and above with wrap
|
||||
# confirm precondition that line 2 is wrapped
|
||||
assert_true(buffer_service.buffer.lines.get_line(2).is_wrapped)
|
||||
buffer_service.buffer.y = 1
|
||||
buffer_service.buffer.x = 90 # Cursor is beyond last column
|
||||
input_handler.erase_in_display(Params.from_array([1]));
|
||||
assert_false(buffer_service.buffer.lines.get_line(2).is_wrapped)
|
||||
|
||||
|
||||
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(["¥¥", "¥"]))
|
|
@ -1,222 +0,0 @@
|
|||
# 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]])
|
||||
|
||||
|
||||
func test_has_sub_params_get_sub_params():
|
||||
params = Params.from_array([38, [2, 50, 100, 150], 5, [], 6])
|
||||
assert_eq(params.has_sub_params(0), true)
|
||||
assert_eq(params.get_sub_params(0), [2, 50, 100, 150])
|
||||
assert_eq(params.has_sub_params(1), false)
|
||||
assert_eq(params.get_sub_params(1), null)
|
||||
assert_eq(params.has_sub_params(2), false)
|
||||
assert_eq(params.get_sub_params(2), null)
|
||||
|
||||
|
||||
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
|
||||
])
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue