diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 2f37b95..966ef8d 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -5,7 +5,7 @@ name: Build backend NET on: push: - branches: [ "master", "GitActions" ] + branches: [ "master" ] pull_request: branches: [ "master" ] @@ -69,16 +69,30 @@ jobs: uses: actions/setup-python@v5 with: python-version: '3.x' + + # Install Python dependencies + - name: Install dependencies + run: | + python -m pip install --upgrade pip - # Run Python Discovery Test - - name: Run Discovery tests + - name: test with pytest working-directory: ./backend/Tests - run: python3 Discovery_Test.py + run: | + pip install pytest pytest-cov + echo "Printing files in current directory" + ls + echo "Running tests" + pytest -v --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html - # Run Python test script - - name: Run API tests - working-directory: ./backend/Tests - run: python3 API_Test.py + # # Run Python Discovery Test + # - name: Run Discovery tests + # working-directory: ./backend/Tests + # run: python3 Discovery_Test.py + + # # Run Python test script + # - name: Run API tests + # working-directory: ./backend/Tests + # run: python3 API_Test.py # Stop backend process after tests - name: Stop backend diff --git a/.gitignore b/.gitignore index 9b135ed..535ff0f 100644 --- a/.gitignore +++ b/.gitignore @@ -415,4 +415,8 @@ FodyWeavers.xsd *.msi *.msix *.msm -*.msp \ No newline at end of file +*.msp + +# pytest cache files +junit/ +.pytest_cache \ No newline at end of file diff --git a/backend/Tests/API_Test.py b/backend/Tests/API_Test.py deleted file mode 100644 index b10abf9..0000000 --- a/backend/Tests/API_Test.py +++ /dev/null @@ -1,72 +0,0 @@ -import socket -import time - -IP = "127.0.0.1" -PORT = 3391 - -DISCOVERY_PORT = 50130 -BUFFER_SIZE = 1024 -DISCOVERY_MESSAGE = "DISCOVER_LOCAL_HOMESERVER" - - -class bcolors: - HEADER = '\033[95m' - OKBLUE = '\033[94m' - OKCYAN = '\033[96m' - OKGREEN = '\033[92m' - WARNING = '\033[93m' - FAIL = '\033[91m' - ENDC = '\033[0m' - BOLD = '\033[1m' - UNDERLINE = '\033[4m' - -totalRunTime = 0.0 - -def main(): - global totalRunTime - - print("Searching for server") - - print("=====================Starting API Tests=======================") - TestAPI('{"Path":"/api/process/start", "Type":"UPDATE", "Data":"Minecraft Server"}') - TestAPI('{"Path":"/api/processes", "Type":"GET", "Data":"Test"}') - TestAPI('{"Path":"/api/processes/status", "Type":"GET", "Data":"Test"}') - TestAPI('{"Path":"/api/process/lastlogs", "Type":"GET", "Data":"Minecraft Server"}') - TestAPI('{"Path":"/api/process/lasterrors", "Type":"GET", "Data":"Minecraft Server"}') - TestAPI('{"Path":"/api/processes", "Type":"POST", "Data":"Invalid Data"}') - TestAPI('{"Path":"/api/fsdfasdf", "Type":"GET", "Data":"Invalid Data"}') - TestAPI('{"Path":"/api/processes", "Type":"migga", "Data":"Invalid Data"}') - TestAPI('{"Path":"/api/process/stop", "Type":"UPDATE", "Data":"Test"}') - time.sleep(5) - TestAPI('{"Path":"api/process/input", "Type":"POST", "Data":"{\\"ProcessTag\\": \\"Minecraft Server\\", \\"Input\\": \\"say hello API\\"}"}') - time.sleep(10) - TestAPI('{"Path":"/api/process/stop", "Type":"UPDATE", "Data":"Minecraft Server"}') - - print(f"Execution time: {totalRunTime:.4f} seconds") - - -def TestAPI(message): - global totalRunTime - - print ("Testing API with message:", message) - try: - print("Trying to connect: " + str((IP, PORT)) ) - with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: - s.connect((IP, PORT)) - s.sendall(message.encode()) - - StartTime = time.perf_counter() - data = s.recv(1024) - elapsed_time = time.perf_counter() - StartTime - totalRunTime += elapsed_time - print(f"{bcolors.OKGREEN} {data.decode()} {bcolors.ENDC}") - print(f"{bcolors.OKCYAN}{bcolors.BOLD} Answer time: {(elapsed_time * 1000):.0f} ms{bcolors.ENDC}") - - except Exception as err: - print(f"{bcolors.FAIL} Failed to message API: {err} {bcolors.ENDC}") - - print("\n\n") - - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/backend/Tests/test_API.py b/backend/Tests/test_API.py new file mode 100644 index 0000000..677c603 --- /dev/null +++ b/backend/Tests/test_API.py @@ -0,0 +1,140 @@ +import socket +import time +import json + +IP = "127.0.0.1" +PORT = 3391 + +DISCOVERY_PORT = 50130 +BUFFER_SIZE = 1024 +DISCOVERY_MESSAGE = "DISCOVER_LOCAL_HOMESERVER" + +# approve testcase if API worked but context not found +DEFAULT_ALLOW_NOT_FOUND = True + +class bcolors: + HEADER = '\033[95m' + OKBLUE = '\033[94m' + OKCYAN = '\033[96m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + ENDC = '\033[0m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + +totalRunTime = 0.0 + +def test_StartProcess(): + ans = ConnectToAPI('{"Path":"/api/process/start", "Type":"UPDATE", "Data":"Minecraft Server"}') + assert isAnswerSuccess(ans) + + +def test_GetProcesses(): + ans = ConnectToAPI('{"Path":"/api/processes", "Type":"GET", "Data":"Test"}') + assert isAnswerSuccess(ans) + + +def test_GetProcessStatus(): + ans = ConnectToAPI('{"Path":"/api/processes/status", "Type":"GET", "Data":"Test"}') + assert isAnswerSuccess(ans) + + +def test_LastLogs(): + ans = ConnectToAPI('{"Path":"/api/process/lastlogs", "Type":"GET", "Data":"Minecraft Server"}') + assert isAnswerSuccess(ans) + + +def test_LastErrors(): + ans = ConnectToAPI('{"Path":"/api/process/lasterrors", "Type":"GET", "Data":"Minecraft Server"}') + assert isAnswerSuccess(ans) + +def test_InvalidProcesses(): + ans = ConnectToAPI('{"Path":"/api/processes", "Type":"POST", "Data":"Invalid Data"}') + assert not isAnswerSuccess(ans, False) + +def test_InvalidPath(): + ans = ConnectToAPI('{"Path":"/api/fsdfasdf", "Type":"GET", "Data":"Invalid Data"}') + assert not isAnswerSuccess(ans, False) + +def test_InvalidType(): + ans = ConnectToAPI('{"Path":"/api/processes", "Type":"migga", "Data":"Invalid Data"}') + assert not isAnswerSuccess(ans, False) + +def test_StopProcess(): + ans = ConnectToAPI('{"Path":"/api/process/stop", "Type":"UPDATE", "Data":"Test"}') + assert isAnswerSuccess(ans) + +def test_ProcessInput(): + ans = ConnectToAPI('{"Path":"api/process/input", "Type":"POST", "Data":"{\\"ProcessTag\\": \\"Minecraft Server\\", \\"Input\\": \\"say hello API\\"}"}') + assert isAnswerSuccess(ans) + +def test_ProcessStop(): + ans = ConnectToAPI('{"Path":"/api/process/stop", "Type":"UPDATE", "Data":"Minecraft Server"}') + assert isAnswerSuccess(ans) + +def isAnswerSuccess(ans: json, Allow_not_found: bool = DEFAULT_ALLOW_NOT_FOUND) -> bool: + ''' + Getting the API answer and returning if the answer is status code is success +
ans: Server Answer +
Allow_not_found: Allowing the answer to be 404 if the API path found but context wasn't + ''' + # if the answer isn't unknown so the API worked but the data was not found + if (Allow_not_found and ans["StatusCode"] == 404): + if "unknown" not in ans["Data"]: + return True + + return ans["StatusCode"] < 300 + + +''' +def main(): + global totalRunTime + + print("Searching for server") + + print("=====================Starting API Tests=======================") + ConnectToAPI('{"Path":"/api/process/start", "Type":"UPDATE", "Data":"Minecraft Server"}') + ConnectToAPI('{"Path":"/api/processes", "Type":"GET", "Data":"Test"}') + ConnectToAPI('{"Path":"/api/processes/status", "Type":"GET", "Data":"Test"}') + ConnectToAPI('{"Path":"/api/process/lastlogs", "Type":"GET", "Data":"Minecraft Server"}') + ConnectToAPI('{"Path":"/api/process/lasterrors", "Type":"GET", "Data":"Minecraft Server"}') + ConnectToAPI('{"Path":"/api/fsdfasdf", "Type":"GET", "Data":"Invalid Data"}') + ConnectToAPI('{"Path":"/api/processes", "Type":"migga", "Data":"Invalid Data"}') + ConnectToAPI('{"Path":"/api/process/stop", "Type":"UPDATE", "Data":"Test"}') + time.sleep(5) + ConnectToAPI('{"Path":"api/process/input", "Type":"POST", "Data":"{\\"ProcessTag\\": \\"Minecraft Server\\", \\"Input\\": \\"say hello API\\"}"}') + time.sleep(10) + ConnectToAPI('{"Path":"/api/process/stop", "Type":"UPDATE", "Data":"Minecraft Server"}') + + print(f"Execution time: {totalRunTime:.4f} seconds") +''' + +def ConnectToAPI(message): + global totalRunTime + + print ("Testing API with message:", message) + try: + print("Trying to connect: " + str((IP, PORT)) ) + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.settimeout(2) + s.connect((IP, PORT)) + s.sendall(message.encode()) + + StartTime = time.perf_counter() + data = s.recv(1024) + elapsed_time = time.perf_counter() - StartTime + totalRunTime += elapsed_time + print(f"{bcolors.OKGREEN} {data.decode()} {bcolors.ENDC}") + print(f"{bcolors.OKCYAN}{bcolors.BOLD} Answer time: {(elapsed_time * 1000):.0f} ms{bcolors.ENDC}") + + except Exception as err: + raise Exception (f"Failed to message API: {err}") + + print("\n\n") + return json.loads(data.decode()) + + +if __name__ == "__main__": + print("Pls use pytest") + exit(-1) \ No newline at end of file diff --git a/backend/Tests/Discovery_Test.py b/backend/Tests/test_Discovery.py similarity index 82% rename from backend/Tests/Discovery_Test.py rename to backend/Tests/test_Discovery.py index 652befd..46c099e 100644 --- a/backend/Tests/Discovery_Test.py +++ b/backend/Tests/test_Discovery.py @@ -1,5 +1,6 @@ import socket import time +import sys IP = "127.0.0.1" PORT = 3391 @@ -20,14 +21,16 @@ class bcolors: UNDERLINE = '\033[4m' -def main(): - if discover_server(): - print(f"{bcolors.OKGREEN} Server found {IP} {bcolors.ENDC}") +def eprint(*args, **kwargs): + ''' + printing error + ''' + print(*args, file=sys.stderr, **kwargs) - else: - print(f"{bcolors.FAIL} Failed to find server! {bcolors.ENDC}") - exit(1) +def test_Discovery(): + '''Testing if we able to discover the server''' + assert discover_server() def discover_server(timeout=5): global IP @@ -63,11 +66,12 @@ def discover_server(timeout=5): Succeeded = True except socket.timeout: - print("No server response received within timeout.") + raise TimeoutError("No server response received within time window.") finally: client_socket.close() return Succeeded if __name__ == "__main__": - main() \ No newline at end of file + print("Pls run pytest") + exit(-1) \ No newline at end of file