Files
VRCT/src-python/backend_test.py

685 lines
31 KiB
Python

# 初期化のため、config.jsonの削除
import os
import time
import random
if os.path.exists("config.json"):
os.remove("config.json")
from mainloop import main_instance
class Color:
BLACK = '\033[30m'#(文字)黒
RED = '\033[31m'#(文字)赤
GREEN = '\033[32m'#(文字)緑
YELLOW = '\033[33m'#(文字)黄
BLUE = '\033[34m'#(文字)青
MAGENTA = '\033[35m'#(文字)マゼンタ
CYAN = '\033[36m'#(文字)シアン
WHITE = '\033[37m'#(文字)白
COLOR_DEFAULT = '\033[39m'#文字色をデフォルトに戻す
BOLD = '\033[1m'#太字
UNDERLINE = '\033[4m'#下線
INVISIBLE = '\033[08m'#不可視
REVERCE = '\033[07m'#文字色と背景色を反転
BG_BLACK = '\033[40m'#(背景)黒
BG_RED = '\033[41m'#(背景)赤
BG_GREEN = '\033[42m'#(背景)緑
BG_YELLOW = '\033[43m'#(背景)黄
BG_BLUE = '\033[44m'#(背景)青
BG_MAGENTA = '\033[45m'#(背景)マゼンタ
BG_CYAN = '\033[46m'#(背景)シアン
BG_WHITE = '\033[47m'#(背景)白
BG_DEFAULT = '\033[49m'#背景色をデフォルトに戻す
RESET = '\033[0m'#全てリセット
class TestMainloop():
def __init__(self):
self.main = main_instance
self.main.startReceiver()
self.main.startHandler()
def stop_main():
pass
self.main.controller.setWatchdogCallback(stop_main)
self.main.controller.init()
# mappingのすべてのstatusをTrueにする
for key in self.main.mapping.keys():
self.main.mapping[key]["status"] = True
self.config_dict = {}
for endpoint in self.main.mapping.keys():
if endpoint.startswith("/get/data/"):
self.config_dict[endpoint.split("/")[-1]], _ = self.main.handleRequest(endpoint, None)
elif endpoint.startswith("/set/disable/"):
self.config_dict[endpoint.split("/")[-1]], _ = self.main.handleRequest(endpoint, None)
print(self.config_dict, flush=True)
self.validity_endpoints = []
for endpoint in self.main.mapping.keys():
if endpoint.startswith("/set/enable/") or endpoint.startswith("/set/disable/"):
self.validity_endpoints.append(endpoint)
self.set_data_endpoints = []
for endpoint in self.main.mapping.keys():
if endpoint.startswith("/set/data/"):
self.set_data_endpoints.append(endpoint)
self.delete_data_endpoints = []
for endpoint in self.main.mapping.keys():
if endpoint.startswith("/delete/data/"):
self.delete_data_endpoints.append(endpoint)
self.run_endpoints = []
for endpoint in self.main.mapping.keys():
if endpoint.startswith("/run/"):
self.run_endpoints.append(endpoint)
self.test_results = {}
def record_test_result(self, endpoint, status, result, expected_status):
"""
テスト結果を記録する
:param endpoint: テスト対象のエンドポイント
:param status: 実際のステータスコード
:param result: 実際の結果
:param expected_status: 期待されるステータスコード
"""
self.test_results[endpoint] = {
"status": status,
"result": result,
"expected_status": expected_status,
"success": status in expected_status
}
def test_endpoints_on_off_single(self, endpoint):
success = False
expected_status = [200]
if endpoint.startswith("/set/enable/"):
match endpoint:
case "/set/enable/websocket_server":
expected_status = [200, 400]
case _:
pass
result, status = self.main.handleRequest(endpoint, None)
if status in expected_status:
if status == 200:
self.config_dict[endpoint.split("/")[-1]] = result
print(f"-> {Color.GREEN}[PASS]{Color.RESET} endpoint:{endpoint} Status: {status}, Result: {result}")
success = True
else:
print(f"-> {Color.RED}[ERROR]{Color.RESET} endpoint:{endpoint} Status: {status}, Result: {result}")
print(f"Current config_dict: {self.config_dict}")
elif endpoint.startswith("/set/disable/"):
result, status = self.main.handleRequest(endpoint, None)
if status in expected_status:
if status == 200:
self.config_dict[endpoint.split("/")[-1]] = result
print(f"-> {Color.GREEN}[PASS]{Color.RESET} endpoint:{endpoint} Status: {status}, Result: {result}")
success = True
else:
print(f"-> {Color.RED}[ERROR]{Color.RESET} endpoint:{endpoint} Status: {status}, Result: {result}")
print(f"Current config_dict: {self.config_dict}")
self.record_test_result(endpoint, status, result, expected_status)
return success
def test_endpoints_on_off_all(self):
print("----ON/OFF系のエンドポイントのテスト----")
for endpoint in self.validity_endpoints:
print(f"Testing endpoint: {endpoint}", flush=True)
self.test_endpoints_on_off_single(endpoint)
print("----ON/OFF系のエンドポイントのテスト終了----")
def test_endpoints_on_off_random(self):
print("----ON/OFFでのランダムアクセスのテスト----")
for i in range(1000):
endpoint = random.choice(self.validity_endpoints)
print(f"No.{i:04} Testing endpoint: {endpoint}", flush=True)
if self.test_endpoints_on_off_single(endpoint) is False:
break
# 最後にすべてOFFにして終了
for endpoint in self.validity_endpoints:
if endpoint.startswith("/set/disable/"):
result, status = self.main.handleRequest(endpoint, None)
time.sleep(0.2)
print("----ON/OFFでのランダムアクセスのテスト終了----")
def test_endpoints_on_off_continuous(self):
print("----ON/OFF連続テスト----")
endpoints = ["/set/enable/websocket_server", "/set/disable/websocket_server"]
# endpoints = [
# "/set/enable/translation",
# "/set/disable/translation",
# "/set/enable/transcription_send",
# "/set/disable/transcription_send",
# "/set/enable/transcription_receive",
# "/set/disable/transcription_receive",
# ]
for i in range(1000):
endpoint = random.choice(endpoints)
print(f"No.{i:04} Testing endpoint: {endpoint}", flush=True)
if self.test_endpoints_on_off_single(endpoint) is False:
break
# 最後にすべてOFFにして終了
for endpoint in self.validity_endpoints:
if endpoint.startswith("/set/disable/"):
result, status = self.main.handleRequest(endpoint, None)
print("----ON/OFF連続テスト終了----")
def test_set_data_endpoints_single(self, endpoint):
success = False
expected_status = [200]
match endpoint:
case "/set/data/selected_tab_no":
data = random.choice(["1", "2", "3"])
case "/set/data/selected_translation_engines":
translation_engines = self.config_dict.get("translation_engines", None)
data = {}
for i in ["1", "2", "3"]:
data[i] = random.choice(translation_engines)
case "/set/data/selected_your_languages":
selectable_language_list = self.config_dict.get("selectable_language_list", None)
data = {}
for i in ["1", "2", "3"]:
data[i] = {}
data[i]["1"] = random.choice(selectable_language_list) | {"enable": True}
case "/set/data/selected_target_languages":
selectable_language_list = self.config_dict.get("selectable_language_list", None)
data = {}
for i in ["1", "2", "3"]:
data[i] = {}
for j in ["1", "2", "3"]:
data[i][j] = random.choice(selectable_language_list) | {"enable": random.choice([True, False])}
case "/set/data/selected_transcription_engine":
transcription_engines = self.config_dict.get("transcription_engines", None)
data = random.choice(transcription_engines)
case "/set/data/transparency":
data = random.randint(0, 100)
case "/set/data/ui_scaling":
data = random.randint(50, 200)
case "/set/data/textbox_ui_scaling":
data = random.randint(50, 200)
case "/set/data/message_box_ratio":
data = round(random.uniform(0.1, 0.9), 2)
case "/set/data/send_message_button_type":
data = random.choice(["show", "hide", "show_and_disable_enter_key"])
case "/set/data/font_family":
data = random.choice(["Arial", "Verdana", "Times New Roman"])
case "/set/data/ui_language":
data = random.choice(["en", "ja", "ko", "zh-Hant", "zh-Hans"])
case "/set/data/main_window_geometry":
data = {
"x_pos": random.randint(0, 1920),
"y_pos": random.randint(0, 1080),
"width": random.randint(800, 1920),
"height": random.randint(600, 1080)
}
case "/set/data/selected_translation_compute_device":
data = random.choice(self.config_dict["translation_compute_device_list"])
case "/set/data/selected_transcription_compute_device":
data = random.choice(self.config_dict["transcription_compute_device_list"])
case "/set/data/ctranslate2_weight_type":
data = random.choice(list(self.config_dict["selectable_ctranslate2_weight_type_dict"].keys()))
case "/set/data/deepl_auth_key":
data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
expected_status = [400]
case "/set/data/selected_mic_host":
data = random.choice(self.config_dict["mic_host_list"])
case "/set/data/selected_mic_device":
data = random.choice(self.config_dict["mic_device_list"])
case "/set/data/mic_threshold":
data = random.randint(-1000, 3000)
if 0 <= data <= 2000:
pass
else:
expected_status = [400]
case "/set/data/mic_record_timeout":
data = random.randint(-1, 10)
if 0 <= data <= self.config_dict["mic_phrase_timeout"]:
pass
else:
expected_status = [400]
case "/set/data/mic_phrase_timeout":
data = random.randint(-1, 10)
if self.config_dict["mic_record_timeout"] <= data:
pass
else:
expected_status = [400]
case "/set/data/mic_max_phrases":
data = random.randint(-1, 10)
if 0 <= data:
pass
else:
expected_status = [400]
case "/set/data/hotkeys":
data = {
'toggle_vrct_visibility': None,
'toggle_translation': None,
'toggle_transcription_send': None,
'toggle_transcription_receive': None
}
case "/set/data/plugins_status":
data = {plugin: random.choice([True, False]) for plugin in self.config_dict.get("plugins", [])}
case "/set/data/mic_avg_logprob":
data = random.uniform(-5, 0)
case "/set/data/mic_no_speech_prob":
data = random.uniform(0, 1)
case "/set/data/mic_word_filter":
data = random.choice(
[
["test_0_0", "test_0_1", "test_0_2", None],
["test_1_0", "test_1_1", None],
["test_2_0", None],
[None]
]
)
case "/set/data/selected_speaker_device":
data = random.choice(self.config_dict["speaker_device_list"])
case "/set/data/speaker_threshold":
data = random.randint(-1000, 5000)
if 0 <= data <= 4000:
pass
else:
expected_status = [400]
case "/set/data/speaker_record_timeout":
data = random.randint(-1, 10)
if 0 <= data <= self.config_dict["speaker_phrase_timeout"]:
pass
else:
expected_status = [400]
case "/set/data/speaker_phrase_timeout":
data = random.randint(-1, 10)
if self.config_dict["speaker_record_timeout"] <= data:
pass
else:
expected_status = [400]
case "/set/data/speaker_max_phrases":
data = random.randint(-1, 10)
if 0 <= data:
pass
else:
expected_status = [400]
case "/set/data/speaker_avg_logprob":
data = random.uniform(-5, 0)
case "/set/data/speaker_no_speech_prob":
data = random.uniform(0, 1)
case "/set/data/whisper_weight_type":
data = random.choice([key for key, value in self.config_dict["selectable_whisper_weight_type_dict"].items() if value is True])
case "/set/data/overlay_small_log_settings":
data = {
"x_pos": random.random(),
"y_pos": random.random(),
"z_pos": random.random(),
"x_rotation": random.random(),
"y_rotation": random.random(),
"z_rotation": random.random(),
"display_duration": random.randint(0, 100),
"fadeout_duration": random.randint(0, 100),
"opacity": random.random(),
"ui_scaling": random.random(),
"tracker": random.choice(["HMD", "LeftHand", "RightHand"]),
}
case "/set/data/overlay_large_log_settings":
data = {
"x_pos": random.random(),
"y_pos": random.random(),
"z_pos": random.random(),
"x_rotation": random.random(),
"y_rotation": random.random(),
"z_rotation": random.random(),
"display_duration": random.randint(0, 100),
"fadeout_duration": random.randint(0, 100),
"opacity": random.random(),
"ui_scaling": random.random(),
"tracker": random.choice(["HMD", "LeftHand", "RightHand"]),
}
case "/set/data/send_message_format_parts":
data = self.config_dict["send_message_format_parts"]
case "/set/data/received_message_format_parts":
data = self.config_dict["received_message_format_parts"]
case "/set/data/websocket_host":
data = random.choice(["127.0.0.1", "aaaaadwafasdsd", "0210.1564.845.0"])
if data == "127.0.0.1":
expected_status = [200, 400]
else:
expected_status = [400]
case "/set/data/websocket_port":
data = random.randint(1024, 65535)
expected_status = [200, 400]
case "/set/data/osc_ip_address":
data = random.choice(["127.0.0.1", "aaaaadwafasdsd", "0210.1564.845.0"])
if data == "127.0.0.1":
pass
else:
expected_status = [400]
case "/set/data/osc_port":
data = random.randint(1024, 65535)
case "/set/data/selected_translation_compute_type":
data = random.choice(self.config_dict["selected_translation_compute_device"]["compute_types"])
case "/set/data/selected_transcription_compute_type":
data = random.choice(self.config_dict["selected_transcription_compute_device"]["compute_types"])
case _:
data = None
expected_status = [404]
if expected_status == [401]:
print(f"-> {Color.YELLOW}[SKIP]{Color.RESET} No test available for this endpoint: {endpoint}.")
self.record_test_result(endpoint, None, None, expected_status) # テスト結果を記録
return success
elif expected_status == [404]:
print(f"-> {Color.RED}[ERROR]{Color.RESET} Unknown endpoint: {endpoint}.")
self.record_test_result(endpoint, None, None, expected_status) # テスト結果を記録
return False
if data is not None:
print(f"data: {data}", end=" ", flush=True)
result, status = self.main.handleRequest(endpoint, data)
if status in expected_status:
if status == 200:
self.config_dict[endpoint.split("/")[-1]] = result
print(f"-> {Color.GREEN}[PASS]{Color.RESET} endpoint:{endpoint} Status: {status}, Result: {result}")
success = True
else:
print(f"-> {Color.RED}[ERROR]{Color.RESET} endpoint:{endpoint} Status: {status}, Result: {result}")
print(f" Current config_dict: {self.config_dict}")
else:
print(f"-> {Color.YELLOW}[SKIP]{Color.RESET} No data to set for this endpoint: {endpoint}.")
success = True
self.record_test_result(endpoint, status, result if data is not None else None, expected_status) # テスト結果を記録
return success
def test_set_data_endpoints_all(self):
print("----データ設定系のエンドポイントのテスト----")
for endpoint in self.set_data_endpoints:
print(f"Testing endpoint: {endpoint}", end=" ", flush=True)
self.test_set_data_endpoints_single(endpoint)
print("----データ設定系のエンドポイントのテスト終了----")
def test_run_endpoints_single(self, endpoint):
success = False
expected_status = [200]
match endpoint:
case "/run/send_message_box":
data_list = [
{
"data": {"id":"000001", "message":"test"},
"status": [200],
},
{
# 英語
"data": {"id":"000002", "message":"Hello World!"},
"status": [200],
},
{
# 日本語
"data": {"id":"000003", "message":"こんにちわ 世界!"},
"status": [200],
},
{
# 韓国語
"data": {"id":"000004", "message":"안녕하세요 세계!"},
"status": [200],
},
{
# 中国語 繁体字
"data": {"id":"000005", "message":"你好,世界!"},
"status": [200],
},
]
choice_data = random.choice(data_list)
data, expected_status = choice_data["data"], choice_data["status"]
case "/run/typing_message_box":
data = None
case "/run/stop_typing_message_box":
data = None
case "/run/send_text_overlay":
data = "test_overlay"
case "/run/swap_your_language_and_target_language":
data = None
case "/run/update_software":
data = None
expected_status = [401] # !!!Cant be tested here!!!
case "/run/update_cuda_software":
data = None
expected_status = [401] # !!!Cant be tested here!!!
case "/run/download_ctranslate2_weight":
data_list = random.choice(["small", "large"])
data = random.choice(data_list)
expected_status = [401] # !!!Cant be tested here!!!
case "/run/download_whisper_weight":
data_list = [
"tiny", "base", "small", "medium",
"large-v1", "large-v2", "large-v3",
"large-v3-turbo-int8", "large-v3-turbo"
]
data = random.choice(data_list)
expected_status = [401] # !!!Cant be tested here!!!
case "/run/open_filepath_logs":
data = None
expected_status = [401] # !!!Cant be tested here!!!
case "/run/open_filepath_config_file":
data = None
expected_status = [401] # !!!Cant be tested here!!!
case "/run/feed_watchdog":
data = None
expected_status = [401] # !!!Cant be tested here!!!
case _:
data = None
expected_status = [404]
success = True
if expected_status == [401]:
print(f"-> {Color.YELLOW}[SKIP]{Color.RESET} No test available for this endpoint: {endpoint}.")
self.record_test_result(endpoint, None, None, expected_status) # テスト結果を記録
return success
elif expected_status == [404]:
print(f"-> {Color.RED}[ERROR]{Color.RESET} Unknown endpoint: {endpoint}.")
self.record_test_result(endpoint, None, None, expected_status) # テスト結果を記録
return False
result, status = self.main.handleRequest(endpoint, data)
if status in expected_status:
print(f"-> {Color.GREEN}[PASS]{Color.RESET} endpoint:{endpoint} Status: {status}, Result: {result}")
success = True
else:
print(f"-> {Color.RED}[ERROR]{Color.RESET} endpoint:{endpoint} Status: {status}, Result: {result}")
print(f"Current config_dict: {self.config_dict}")
self.record_test_result(endpoint, status, result, expected_status) # テスト結果を記録
return success
def test_run_endpoints_all(self):
print("----実行系のエンドポイントのテスト----")
for endpoint in self.run_endpoints:
print(f"Testing endpoint: {endpoint}", end=" ", flush=True)
self.test_run_endpoints_single(endpoint)
print("----実行系のエンドポイントのテスト終了----")
def test_endpoints_all_random(self):
print("----すべてのエンドポイントのランダムアクセスのテスト----")
endpoint_types = [
"validity",
"set_data",
"run",
"delete",
]
for i in range(10000):
endpoints_type = random.choice(endpoint_types)
match endpoints_type:
case "validity":
endpoint = random.choice(self.validity_endpoints)
print(f"No.{i:04} Testing endpoint: {endpoint}", flush=True)
if self.test_endpoints_on_off_single(endpoint) is False:
break
case "set_data":
endpoint = random.choice(self.set_data_endpoints)
print(f"No.{i:04} Testing endpoint: {endpoint}", flush=True)
if self.test_set_data_endpoints_single(endpoint) is False:
break
case "run":
endpoint = random.choice(self.run_endpoints)
print(f"No.{i:04} Testing endpoint: {endpoint}", flush=True)
if self.test_run_endpoints_single(endpoint) is False:
break
case "delete":
endpoint = random.choice(self.delete_data_endpoints)
print(f"No.{i:04} Testing endpoint: {endpoint}", flush=True)
if self.test_delete_data_endpoints_single(endpoint) is False:
break
# 最後にすべてOFFにして終了
for endpoint in self.validity_endpoints:
if endpoint.startswith("/set/disable/"):
_, _ = self.main.handleRequest(endpoint, None)
print("----すべてのエンドポイントのランダムアクセスのテスト終了----")
def test_endpoints_specific_random(self):
print("----特定のエンドポイントのランダムアクセスのテスト----")
self.validity_specific_endpoints = [
"/set/enable/websocket_server",
"/set/disable/websocket_server",
]
self.set_data_specific_endpoints = [
"/set/data/ctranslate2_weight_type",
"/set/data/websocket_host",
"/set/data/websocket_port",
"/set/data/osc_ip_address",
"/set/data/osc_port",
]
self.run_specific_endpoints = []
self.delete_data_endpoints = []
endpoint_types = [
"validity",
"set_data",
# "run",
# "delete",
]
for i in range(1000):
endpoints_type = random.choice(endpoint_types)
match endpoints_type:
case "validity":
endpoint = random.choice(self.validity_specific_endpoints)
print(f"No.{i:04} Testing endpoint: {endpoint}", flush=True)
if self.test_endpoints_on_off_single(endpoint) is False:
break
case "set_data":
endpoint = random.choice(self.set_data_specific_endpoints)
print(f"No.{i:04} Testing endpoint: {endpoint}", flush=True)
if self.test_set_data_endpoints_single(endpoint) is False:
break
case "run":
endpoint = random.choice(self.run_specific_endpoints)
print(f"No.{i:04} Testing endpoint: {endpoint}", flush=True)
if self.test_run_endpoints_single(endpoint) is False:
break
case "delete":
endpoint = random.choice(self.delete_data_endpoints)
print(f"No.{i:04} Testing endpoint: {endpoint}", flush=True)
if self.test_delete_data_endpoints_single(endpoint) is False:
break
# 最後にすべてOFFにして終了
for endpoint in self.validity_endpoints:
if endpoint.startswith("/set/disable/"):
_, _ = self.main.handleRequest(endpoint, None)
print("----特定のエンドポイントのランダムアクセスのテスト終了----")
def test_delete_data_endpoints_single(self, endpoint):
success = False
expected_status = [200]
match endpoint:
case "/delete/data/deepl_auth_key":
data = None
case _:
data = None
expected_status = [404]
success = True
if expected_status == [404]:
print(f"-> {Color.RED}[ERROR]{Color.RESET} Unknown endpoint: {endpoint}.")
self.record_test_result(endpoint, None, None, expected_status) # テスト結果を記録
return False
result, status = self.main.handleRequest(endpoint, data)
if status in expected_status:
print(f"-> {Color.GREEN}[PASS]{Color.RESET} endpoint:{endpoint} Status: {status}, Result: {result}")
success = True
else:
print(f"-> {Color.RED}[ERROR]{Color.RESET} endpoint:{endpoint} Status: {status}, Result: {result}")
print(f"Current config_dict: {self.config_dict}")
self.record_test_result(endpoint, status, result, expected_status) # テスト結果を記録
return success
def test_delete_data_endpoints_all(self):
print("----データ削除系のエンドポイントのテスト----")
for endpoint in self.delete_data_endpoints:
print(f"Testing endpoint: {endpoint}", flush=True)
self.test_delete_data_endpoints_single(endpoint)
print("----データ削除系のエンドポイントのテスト終了----")
def generate_summary(self):
"""
テスト結果のサマリーを生成して表示する
"""
total_tests = len(self.test_results)
passed_tests = sum(1 for result in self.test_results.values() if result["success"])
untested_tests = sum(1 for result in self.test_results.values() if result["expected_status"] == [401])
invalid_tests = sum(1 for result in self.test_results.values() if result["expected_status"] == [404])
failed_tests = total_tests - passed_tests - untested_tests - invalid_tests
print("\n---- テスト結果のサマリー ----")
print(f"総テスト数: {total_tests}")
print(f"成功したテスト数: {passed_tests}")
print(f"失敗したテスト数: {failed_tests}")
print(f"テストをしなかったテスト数: {untested_tests}")
print(f"無効なテスト数: {invalid_tests}\n")
if untested_tests > 0:
print("テストをしなかったテストの詳細:")
for endpoint, result in self.test_results.items():
if result["expected_status"] == [401]:
print(f"- エンドポイント: {endpoint}")
print(f" ステータス: {result['status']}")
print(f" 結果: {result['result']}\n")
if invalid_tests > 0:
print("無効なテストの詳細:")
for endpoint, result in self.test_results.items():
if result["expected_status"] == [404]:
print(f"- エンドポイント: {endpoint}")
print(f" ステータス: {result['status']}")
print(f" 結果: {result['result']}\n")
if failed_tests > 0:
print("失敗したテストの詳細:")
for endpoint, result in self.test_results.items():
if result["success"] != [200]:
print(f"- エンドポイント: {endpoint}")
print(f" ステータス: {result['status']} (期待されるステータス: {result['expected_status']})")
print(f" 結果: {result['result']}\n")
print("---- サマリー終了 ----\n")
if __name__ == "__main__":
import traceback
try:
test = TestMainloop()
test.test_endpoints_on_off_all()
test.test_set_data_endpoints_all()
test.test_run_endpoints_all()
test.test_delete_data_endpoints_all()
# test.test_endpoints_all_random()
# test.test_endpoints_on_off_continuous()
# test.test_endpoints_on_off_random()
# test.test_endpoints_specific_random()
test.generate_summary()
except KeyboardInterrupt:
print("Interrupted by user, shutting down...")
except Exception as e:
traceback.print_exc()
print(f"An error occurred: {e}")