From 115521f645c2ddb2871bba75ee43ed6ecb6570d7 Mon Sep 17 00:00:00 2001 From: Leroy Hopson Date: Sat, 3 Jul 2021 20:54:34 +0700 Subject: [PATCH] Replace Gut with WAT Gut was freezing on some integration tests. It was also entering an infinite loop after exiting (even after closing Godot and VSCode) which caused a `godot.log` file in app_userdata to keep growing until my hard drive was full. --- .gitignore | 6 +- .gutconfig.json | 8 -- addons/godot_xterm/nodes/pty/pty.gd | 5 +- addons/godot_xterm/nodes/pty/unix/pty_unix.gd | 4 + plug.gd | 2 +- project.godot | 30 ++++- test/integration/unix/pty_unix.test.gd | 117 ------------------ test/integration/unix/unix.test.gd | 94 ++++++++++++++ test/integration/uv_utils.test.gd | 31 +++++ test/integration/uv_utils/uv_utils.test.gd | 30 ----- 10 files changed, 165 insertions(+), 162 deletions(-) delete mode 100644 .gutconfig.json delete mode 100644 test/integration/unix/pty_unix.test.gd create mode 100644 test/integration/unix/unix.test.gd create mode 100644 test/integration/uv_utils.test.gd delete mode 100644 test/integration/uv_utils/uv_utils.test.gd diff --git a/.gitignore b/.gitignore index a5c7618..2a5e378 100644 --- a/.gitignore +++ b/.gitignore @@ -20,5 +20,7 @@ mono_crash.* # Package-manager-specific ignores .plugged -# Addon-specific ignores -addons/gut +# Test-specific ignores +addons/WAT +test/results.xml +test/test_metadata.json diff --git a/.gutconfig.json b/.gutconfig.json deleted file mode 100644 index 9473df7..0000000 --- a/.gutconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "dirs": [ - "res://" - ], - "prefix": "", - "suffix": ".test.gd", - "include_subdirs": true -} diff --git a/addons/godot_xterm/nodes/pty/pty.gd b/addons/godot_xterm/nodes/pty/pty.gd index 3e524e0..8893686 100644 --- a/addons/godot_xterm/nodes/pty/pty.gd +++ b/addons/godot_xterm/nodes/pty/pty.gd @@ -226,8 +226,9 @@ func fork( push_error("Not implemented.") -func open(cols: int = DEFAULT_COLS, rows: int = DEFAULT_ROWS) -> void: - pass +func open(cols: int = DEFAULT_COLS, rows: int = DEFAULT_ROWS) -> Array: + assert(false, "Not implemented.") + return [FAILED] func _parse_env(env: Dictionary = {}) -> PoolStringArray: diff --git a/addons/godot_xterm/nodes/pty/unix/pty_unix.gd b/addons/godot_xterm/nodes/pty/unix/pty_unix.gd index f52262b..44d207a 100644 --- a/addons/godot_xterm/nodes/pty/unix/pty_unix.gd +++ b/addons/godot_xterm/nodes/pty/unix/pty_unix.gd @@ -97,6 +97,10 @@ func fork( return OK +func open(cols: int = DEFAULT_COLS, rows: int = DEFAULT_ROWS) -> Array: + return PTYUnix.new().open(cols, rows) + + func _on_pipe_data_received(data): emit_signal("data_received", data) diff --git a/plug.gd b/plug.gd index f86c1b1..e85abf6 100644 --- a/plug.gd +++ b/plug.gd @@ -2,4 +2,4 @@ extends "res://addons/gd-plug/plug.gd" func _plugging(): - plug("bitwes/Gut") + plug("AlexDarigan/WAT", {commit = "2136a1a440711bfdcc77ec8514d7590274bf6fb6"}) diff --git a/project.godot b/project.godot index 4eebafa..0a9757c 100644 --- a/project.godot +++ b/project.godot @@ -13,11 +13,37 @@ _global_script_classes=[ { "class": "GDXterm", "language": "GDScript", "path": "res://addons/godot_xterm/namespace.gd" +}, { +"base": "Reference", +"class": "WAT", +"language": "GDScript", +"path": "res://addons/WAT/namespace.gd" +}, { +"base": "Node", +"class": "WATTest", +"language": "GDScript", +"path": "res://addons/WAT/test/test.gd" } ] _global_script_class_icons={ -"GDXterm": "" +"GDXterm": "", +"WAT": "", +"WATTest": "" } +[WAT] + +Test_Directory="res://test" +Results_Directory="res://test" +Test_Metadata_Directory="res://test" +Tags=PoolStringArray( "unit", "integration", "unix", "windows" ) +Window_Size=Vector2( 1280, 720 ) +Minimize_Window_When_Running_Tests=false +Port=6008 +Run_All_Tests=Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":0,"unicode":0,"echo":false,"script":null) + +Auto_Refresh_Tests=false +Display=8 + [application] config/name="Godot Xterm" @@ -30,7 +56,7 @@ window/vsync/use_vsync=false [editor_plugins] -enabled=PoolStringArray( "res://addons/godot_xterm/plugin.cfg" ) +enabled=PoolStringArray( "res://addons/WAT/plugin.cfg", "res://addons/godot_xterm/plugin.cfg" ) [rendering] diff --git a/test/integration/unix/pty_unix.test.gd b/test/integration/unix/pty_unix.test.gd deleted file mode 100644 index 4429774..0000000 --- a/test/integration/unix/pty_unix.test.gd +++ /dev/null @@ -1,117 +0,0 @@ -extends "res://addons/gut/test.gd" -# WARNING: These test can only be run on the "Unix" platforms (X11, Server, and OSX). -# Some of the tests also rely on listing the files in /dev/pts. If you open or close -# terminals while these tests are running, it may cause inaccurate results. - -const PTYUnixNative := preload("res://addons/godot_xterm/nodes/pty/unix/pty_unix.gdns") -const PTYUnix := preload("res://addons/godot_xterm/nodes/pty/unix/pty_unix.gd") - - -func before_all(): - assert( - OS.get_name() in ["X11", "Server", "OSX"], "Unix only tests cannot be run on this platform." - ) - - -class TestFork: - extends "res://addons/gut/test.gd" - - const PTYUnix := preload("res://addons/godot_xterm/nodes/pty/unix/pty_unix.gd") - - var sh_path: String - - func before_all(): - var output = [] - var exit_code = OS.execute("command", PoolStringArray(["-v", "sh"]), true, output) - assert(exit_code == 0, "sh is required for these tests.") - sh_path = output[0].strip_edges() - - func test_fork_creates_new_pts(): - var num_pts = Helper._get_pts().size() - - var pty = PTYUnix.new() - add_child_autofree(pty) - var err = pty.fork(sh_path) - assert_eq(err, OK) - - var new_num_pts = Helper._get_pts().size() - assert_eq(new_num_pts, num_pts + 1) - - -class TestOpen: - extends "res://addons/gut/test.gd" - - func test_open_creates_new_pts(): - var num_pts = Helper._get_pts().size() - - var result = PTYUnixNative.new().open(0, 0) - assert_eq(result[0], OK) - - var new_num_pts = Helper._get_pts().size() - assert_eq(new_num_pts, num_pts + 1) - - func test_pty_has_correct_name(): - var original_pts = Helper._get_pts() - - var result = PTYUnixNative.new().open(0, 0) - assert_eq(result[0], OK) - - var new_pts = Helper._get_pts() - for pt in original_pts: - new_pts.erase(pt) - assert_true(result[1].pty in new_pts) - - func test_pty_has_correct_win_size(): - var cols = 7684 - var rows = 9314 - - var result = PTYUnixNative.new().open(cols, rows) - assert_eq(result[0], OK) - - var winsize = Helper._get_winsize(result[1].master) - assert_eq(winsize.cols, cols) - assert_eq(winsize.rows, rows) - - -class Helper: - static func _get_pts() -> Array: - var dir := Directory.new() - - if dir.open("/dev/pts") != OK or dir.list_dir_begin(true, true) != OK: - assert(false, "Could not open /dev/pts.") - - var pts := [] - var file_name := dir.get_next() - - while file_name != "": - if file_name.is_valid_integer(): - pts.append("/dev/pts/%s" % file_name) - file_name = dir.get_next() - - return pts - - static func _get_winsize(fd: int) -> Dictionary: - var output = [] - - assert( - OS.execute("command", ["-v", "python"], true, output) == 0, - "Python must be installed to run this test." - ) - var python_path = output[0].strip_edges() - - var exit_code = OS.execute( - python_path, - [ - "-c", - ( - "import struct, fcntl, termios; print(struct.unpack('hh', fcntl.ioctl(%d, termios.TIOCGWINSZ, '1234')))" - % fd - ) - ], - true, - output - ) - assert(exit_code == 0, "Failed to run python command for this test.") - - var size = str2var("Vector2" + output[0].strip_edges()) - return {rows = int(size.x), cols = int(size.y)} diff --git a/test/integration/unix/unix.test.gd b/test/integration/unix/unix.test.gd new file mode 100644 index 0000000..6e82486 --- /dev/null +++ b/test/integration/unix/unix.test.gd @@ -0,0 +1,94 @@ +extends WAT.Test + +var pty: GDXterm.PTYUnix + + +func pre(): + pty = GDXterm.PTYUnix.new() + add_child(pty) + + +func post(): + pty.queue_free() + + +func test_fork_succeeds(): + var err = pty.fork("sh") + asserts.is_equal(err, OK) + + +func test_open_succeeds(): + var result = pty.open() + asserts.is_equal(result[0], OK) + + +func test_open_creates_a_new_pty(): + var num_pts = Helper._get_pts().size() + pty.open() + var new_num_pts = Helper._get_pts().size() + asserts.is_equal(new_num_pts, num_pts + 1) + + +func test_open_pty_has_correct_name(): + var original_pts = Helper._get_pts() + var result = pty.open() + var new_pts = Helper._get_pts() + for pt in original_pts: + new_pts.erase(pt) + asserts.is_equal(result[1].pty, new_pts[0]) + + +func test_open_pty_has_correct_win_size(): + var cols = 7684 + var rows = 9314 + var result = pty.open(cols, rows) + var winsize = Helper._get_winsize(result[1].master) + asserts.is_equal(winsize.cols, cols) + asserts.is_equal(winsize.rows, rows) + + +class Helper: + static func _get_pts() -> Array: + var dir := Directory.new() + + var pty_dir = "/dev/pts" if OS.get_name() == "X11" else "/dev" + var pty_prefix = "tty" if OS.get_name() == "OSX" else "" + + if dir.open(pty_dir) != OK or dir.list_dir_begin(true, true) != OK: + assert(false, "Could not open /dev/pts.") + + var pts := [] + var file_name: String = dir.get_next() + + while file_name != "": + if file_name.trim_prefix(pty_prefix).is_valid_integer(): + pts.append("/dev/pts/%s" % file_name) + file_name = dir.get_next() + + return pts + + static func _get_winsize(fd: int) -> Dictionary: + var output = [] + + assert( + OS.execute("command", ["-v", "python"], true, output) == 0, + "Python must be installed to run this test." + ) + var python_path = output[0].strip_edges() + + var exit_code = OS.execute( + python_path, + [ + "-c", + ( + "import struct, fcntl, termios; print(struct.unpack('hh', fcntl.ioctl(%d, termios.TIOCGWINSZ, '1234')))" + % fd + ) + ], + true, + output + ) + assert(exit_code == 0, "Failed to run python command for this test.") + + var size = str2var("Vector2" + output[0].strip_edges()) + return {rows = int(size.x), cols = int(size.y)} diff --git a/test/integration/uv_utils.test.gd b/test/integration/uv_utils.test.gd new file mode 100644 index 0000000..221f9d4 --- /dev/null +++ b/test/integration/uv_utils.test.gd @@ -0,0 +1,31 @@ +extends WAT.Test + +const LibuvUtils = preload("res://addons/godot_xterm/nodes/pty/libuv_utils.gd") + +const EMPTY_VAR = "GODOT_XTERM_TEST_EMPTY_ENV_VAR" +const TEST_VAR = "GODOT_XTERM_TEST_ENV_VAR" +const TEST_VAL = "TEST123" + +var env: Dictionary + + +func pre(): + assert(OS.set_environment(EMPTY_VAR, "")) + assert(OS.set_environment(TEST_VAR, TEST_VAL)) + env = LibuvUtils.get_os_environ() + + +func test_has_empty_var(): + asserts.has(EMPTY_VAR, env) + + +func test_empty_var_has_empty_val(): + asserts.is_equal(env[EMPTY_VAR], "") + + +func test_has_test_var(): + asserts.has(TEST_VAR, env) + + +func test_test_var_has_correct_val(): + asserts.is_equal(env[TEST_VAR], TEST_VAL) diff --git a/test/integration/uv_utils/uv_utils.test.gd b/test/integration/uv_utils/uv_utils.test.gd deleted file mode 100644 index d41d75c..0000000 --- a/test/integration/uv_utils/uv_utils.test.gd +++ /dev/null @@ -1,30 +0,0 @@ -extends "res://addons/gut/test.gd" - -const LibuvUtils := preload("res://addons/godot_xterm/nodes/pty/libuv_utils.gd") - - -class TestGetOSEnviron: - extends "res://addons/gut/test.gd" - - const EMPTY_VAR = "GODOT_XTERM_TEST_EMPTY_ENV_VAR" - const TEST_VAR = "GODOT_XTERM_TEST_ENV_VAR" - const TEST_VAL = "TEST123" - - var env: Dictionary - - func before_each(): - assert(OS.set_environment(EMPTY_VAR, "")) - assert(OS.set_environment(TEST_VAR, TEST_VAL)) - env = LibuvUtils.get_os_environ() - - func test_has_empty_var(): - assert_has(env, EMPTY_VAR) - - func test_empty_var_has_empty_val(): - assert_eq(env[EMPTY_VAR], "") - - func test_has_test_var(): - assert_has(env, TEST_VAR) - - func test_test_var_has_correct_val(): - assert_eq(env[TEST_VAR], TEST_VAL)