mirror of
https://github.com/lihop/godot-xterm.git
synced 2025-05-14 23:35:30 +02:00
Add/update more files
This commit is contained in:
parent
3307231b65
commit
0769592a1b
44 changed files with 4188 additions and 362 deletions
100
test/unit/parser/test_dcs_parser.gd
Normal file
100
test/unit/parser/test_dcs_parser.gd
Normal file
|
@ -0,0 +1,100 @@
|
|||
# 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],
|
||||
])
|
411
test/unit/parser/test_escape_sequence_parser.gd
Normal file
411
test/unit/parser/test_escape_sequence_parser.gd
Normal file
|
@ -0,0 +1,411 @@
|
|||
# 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()
|
202
test/unit/parser/test_parser.gd
Normal file
202
test/unit/parser/test_parser.gd
Normal file
|
@ -0,0 +1,202 @@
|
|||
# Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
# Ported to GDScript by the GodotXterm authors.
|
||||
# License MIT
|
||||
extends 'res://addons/gut/test.gd'
|
||||
|
||||
const Params = preload("res://addons/godot_xterm/parser/params.gd")
|
||||
|
||||
class TestParams:
|
||||
extends 'res://addons/gut/test.gd'
|
||||
|
||||
var params
|
||||
|
||||
func before_each():
|
||||
params = Params.new()
|
||||
|
||||
func test_respects_ctor_args():
|
||||
params = Params.new(12, 23)
|
||||
assert_eq(params.params.size(), 12)
|
||||
assert_eq(params.sub_params.size(), 23)
|
||||
assert_eq(params.to_array(), [])
|
||||
|
||||
func test_add_param():
|
||||
params.add_param(1)
|
||||
assert_eq(params.length, 1)
|
||||
assert_eq(params.params.slice(0, params.length - 1), [1])
|
||||
assert_eq(params.to_array(), [1])
|
||||
params.add_param(23)
|
||||
assert_eq(params.length, 2)
|
||||
assert_eq(params.params.slice(0, params.length - 1), [1, 23])
|
||||
assert_eq(params.to_array(), [1, 23])
|
||||
assert_eq(params.sub_params_length, 0)
|
||||
|
||||
func test_add_sub_param():
|
||||
params.add_param(1)
|
||||
params.add_sub_param(2)
|
||||
params.add_sub_param(3)
|
||||
assert_eq(params.length, 1)
|
||||
assert_eq(params.sub_params_length, 2)
|
||||
assert_eq(params.to_array(), [1, [2, 3]])
|
||||
params.add_param(12345)
|
||||
params.add_sub_param(-1)
|
||||
assert_eq(params.length, 2)
|
||||
assert_eq(params.sub_params_length, 3)
|
||||
assert_eq(params.to_array(), [1, [2,3], 12345, [-1]])
|
||||
|
||||
func test_should_not_add_sub_params_without_previous_param():
|
||||
params.add_sub_param(2)
|
||||
params.add_sub_param(3)
|
||||
assert_eq(params.length, 0)
|
||||
assert_eq(params.sub_params_length, 0)
|
||||
assert_eq(params.to_array(), [])
|
||||
params.add_param(1)
|
||||
params.add_sub_param(2)
|
||||
params.add_sub_param(3)
|
||||
assert_eq(params.length, 1)
|
||||
assert_eq(params.sub_params_length, 2)
|
||||
assert_eq(params.to_array(), [1, [2, 3]])
|
||||
|
||||
func test_reset():
|
||||
params.add_param(1)
|
||||
params.add_sub_param(2)
|
||||
params.add_sub_param(3)
|
||||
params.add_param(12345)
|
||||
params.reset()
|
||||
assert_eq(params.length, 0)
|
||||
assert_eq(params.sub_params_length, 0)
|
||||
assert_eq(params.to_array(), [])
|
||||
params.add_param(1)
|
||||
params.add_sub_param(2)
|
||||
params.add_sub_param(3)
|
||||
params.add_param(12345)
|
||||
params.add_sub_param(-1)
|
||||
assert_eq(params.length, 2)
|
||||
assert_eq(params.sub_params_length, 3)
|
||||
assert_eq(params.to_array(), [1, [2, 3], 12345, [-1]])
|
||||
|
||||
|
||||
func test_from_array_to_array():
|
||||
var data = []
|
||||
assert_eq(params.from_array(data).to_array(), data)
|
||||
data = [1, [2, 3], 12345, [-1]]
|
||||
assert_eq(params.from_array(data).to_array(), data)
|
||||
data = [38, 2, 50, 100, 150]
|
||||
assert_eq(params.from_array(data).to_array(), data)
|
||||
data = [38, 2, 50, 100, [150]]
|
||||
assert_eq(params.from_array(data).to_array(), data)
|
||||
data = [38, [2, 50, 100, 150]]
|
||||
assert_eq(params.from_array(data).to_array(), data)
|
||||
# strip empty sub params
|
||||
data = [38, [2, 50, 100, 150], 5, [], 6]
|
||||
assert_eq(Params.from_array(data).to_array(), [38, [2, 50, 100, 150], 5, 6])
|
||||
# ignore leading sub params
|
||||
data = [[1,2], 12345, [-1]]
|
||||
assert_eq(Params.from_array(data).to_array(), [12345, [-1]])
|
||||
|
||||
|
||||
class TestParse:
|
||||
extends 'res://addons/gut/test.gd'
|
||||
|
||||
var params
|
||||
|
||||
func parse(params, s):
|
||||
params.reset()
|
||||
params.add_param(0)
|
||||
if typeof(s) == TYPE_STRING:
|
||||
s = [s]
|
||||
for chunk in s:
|
||||
var i = 0
|
||||
while i < chunk.length():
|
||||
# Start for
|
||||
var code = chunk.to_ascii()[i]
|
||||
var do = true
|
||||
while do:
|
||||
match code:
|
||||
0x3b:
|
||||
params.add_param(0)
|
||||
0x3a:
|
||||
params.add_sub_param(-1)
|
||||
_:
|
||||
params.add_digit(code - 48)
|
||||
code = chunk.to_ascii()[i] if i < chunk.length() else 0
|
||||
i+=1
|
||||
do = i < s.size() and code > 0x2f and code < 0x3c
|
||||
i-=1
|
||||
# End for
|
||||
i+=1
|
||||
|
||||
func before_each():
|
||||
params = Params.new()
|
||||
|
||||
func test_param_defaults_to_0(): # ZDM (Zero Default Mode)
|
||||
parse(params, '')
|
||||
assert_eq(params.to_array(), [0])
|
||||
|
||||
func test_sub_param_defaults_to_neg_1():
|
||||
parse(params, ':')
|
||||
assert_eq(params.to_array(), [0, [-1]])
|
||||
|
||||
func test_reset_on_new_sequence():
|
||||
parse(params, '1;2;3')
|
||||
assert_eq(params.to_array(), [1, 2, 3])
|
||||
parse(params, '4')
|
||||
assert_eq(params.to_array(), [4])
|
||||
parse(params, '4::123:5;6;7')
|
||||
assert_eq(params.to_array(), [4, [-1, 123, 5], 6, 7])
|
||||
parse(params, '')
|
||||
assert_eq(params.to_array(), [0])
|
||||
|
||||
func test_should_handle_length_restrictions_correctly():
|
||||
params = Params.new(3, 3)
|
||||
parse(params, '1;2;3')
|
||||
assert_eq(params.to_array(), [1, 2, 3])
|
||||
parse(params, '4')
|
||||
assert_eq(params.to_array(), [4])
|
||||
parse(params, '4::123:5;6;7')
|
||||
assert_eq(params.to_array(), [4, [-1, 123, 5], 6, 7])
|
||||
parse(params, '')
|
||||
assert_eq(params.to_array(), [0])
|
||||
# overlong params
|
||||
parse(params, '4;38:2::50:100:150;48:5:22')
|
||||
assert_eq(params.to_array(), [4, 38, [2, -1, 50], 48])
|
||||
# overlong sub params
|
||||
parse(params, '4;38:2::50:100:150;48:5:22')
|
||||
assert_eq(params.to_array(), [4, 38, [2, -1, 50], 48])
|
||||
|
||||
func test_typical_sequences():
|
||||
# SGR with semicolon syntax
|
||||
parse(params, '0;4;38;2;50;100;150;48;5;22')
|
||||
assert_eq(params.to_array(), [0, 4, 38, 2, 50, 100, 150, 48, 5, 22])
|
||||
# SGR mixed style (partly wrong)
|
||||
parse(params, '0;4;38;2;50:100:150;48;5:22')
|
||||
assert_eq(params.to_array(), [0, 4, 38, 2, 50, [100, 150], 48, 5, [22]])
|
||||
# SGR colon style
|
||||
parse(params, '0;4;38:2::50:100:150;48:5:22')
|
||||
assert_eq(params.to_array(), [0, 4, 38, [2, -1, 50, 100, 150], 48, [5, 22]])
|
||||
|
||||
func test_clamp_parsed_params():
|
||||
parse(params, '2147483648')
|
||||
assert_eq(params.to_array(), [0x7FFFFFFF])
|
||||
|
||||
func test_clamp_parsed_sub_params():
|
||||
parse(params, ':2147483648')
|
||||
assert_eq(params.to_array(), [0, [0x7FFFFFFF]])
|
||||
|
||||
func test_should_cancel_subdigits_if_beyond_params_limit():
|
||||
parse(params, ';;;;;;;;;10;;;;;;;;;;20;;;;;;;;;;30;31;32;33;34;35::::::::')
|
||||
assert_eq(params.to_array(), [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 10,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 20,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, 32
|
||||
])
|
||||
|
||||
# func test_should_carry_forward_is_sub_state():
|
||||
# parse(params, ['1:22:33', '44'])
|
||||
# assert_eq(params.to_array(), [1, [22, 3344]])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue