Преглед изворни кода

Add a preliminary client test suite

	This simply tests the current functionality of the gamemode_client tools by calling each function in turn and checking the values return correctly.

	Requires the gamemode service to currently be running and installed on the system.
Marc Di Luzio пре 6 година
родитељ
комит
0b4e86651e
3 измењених фајлова са 212 додато и 2 уклоњено
  1. 210 0
      daemon/gamemode-tests.c
  2. 1 1
      daemon/gamemode.h
  3. 1 1
      daemon/main.c

+ 210 - 0
daemon/gamemode-tests.c

@@ -0,0 +1,210 @@
+/*
+
+Copyright (c) 2017-2018, Feral Interactive
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+ * Neither the name of Feral Interactive nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+ */
+
+#define _GNU_SOURCE
+
+#include "gamemode.h"
+#include "helpers.h"
+#include "logging.h"
+
+#include <libgen.h>
+#include <unistd.h>
+
+#include "gamemode_client.h"
+
+/* Initial verify step to ensure gamemode isn't already active */
+static int verify_gamemode_initial(void)
+{
+	int status = 0;
+
+	if ((status = gamemode_query_status()) != 0) {
+		fprintf(stderr,
+		        "gamemode is currently active, tests require gamemode to start deactivated!\n");
+		status = -1;
+	} else if (status == -1) {
+		fprintf(stderr, "gamemode_query_status failed: %s!\n", gamemode_error_string());
+		fprintf(stderr, "is gamemode installed correctly?\n");
+		status = -1;
+	} else {
+		status = 0;
+	}
+
+	return status;
+}
+
+/* Check if gamemode is active and this client is registered */
+static int verify_active_and_registered(void)
+{
+	int status = gamemode_query_status();
+
+	if (status != 2) {
+		if (status == -1) {
+			fprintf(stderr, "gamemode_query_status failed: %s\n", gamemode_error_string());
+		} else if (status == 1) {
+			fprintf(stderr, "gamemode was active but did not have this process registered\n");
+		}
+		fprintf(stderr, "gamemode failed to activate correctly when requested (expected 2)!\n");
+		status = -1;
+	} else {
+		status = 0;
+	}
+
+	return status;
+}
+
+/* Ensure gamemode is deactivated when it should be */
+static int verify_deactivated(void)
+{
+	int status = gamemode_query_status();
+
+	if (status != 0) {
+		if (status == -1) {
+			fprintf(stderr, "gamemode_query_status failed: %s\n", gamemode_error_string());
+		}
+		fprintf(stderr, "gamemode failed to deactivate when requested (expected 0)!\n");
+		status = -1;
+	} else {
+		status = 0;
+	}
+
+	return status;
+}
+
+/* Ensure another client is connected */
+static int verify_other_client_connected(void)
+{
+	int status = gamemode_query_status();
+
+	if (status != 1) {
+		if (status == -1) {
+			fprintf(stderr, "gamemode_query_status failed: %s\n", gamemode_error_string());
+		}
+		fprintf(stderr,
+		        "gamemode_query_status failed to return other client connected (expected 1)!\n");
+		status = -1;
+	} else {
+		status = 0;
+	}
+
+	return status;
+}
+
+/**
+ * game_mode_run_client_tests runs a set of tests of the client code
+ * we simply verify that the client can request the status and recieves the correct results
+ *
+ * returns 0 for success, -1 for failure
+ */
+int game_mode_run_client_tests()
+{
+	int status = 0;
+	fprintf(stdout, "running tests on external gamemode instance...\n");
+
+	/* First verify that gamemode is not currently active on the system
+	 * As well as it being currently installed and queryable
+	 */
+	if (verify_gamemode_initial() != 0)
+		return -1;
+
+	/* Verify that gamemode_request_start correctly start gamemode */
+	if (gamemode_request_start() != 0) {
+		fprintf(stderr, "gamemode_request_start failed: %s\n", gamemode_error_string());
+		return -1;
+	}
+
+	/* Verify that gamemode is now active and this client is registered*/
+	if (verify_active_and_registered() != 0)
+		return -1;
+
+	/* Verify that gamemode_request_end corrently de-registers gamemode */
+	if (gamemode_request_end() != 0) {
+		fprintf(stderr, "gamemode_request_end failed: %s!\n", gamemode_error_string());
+		return -1;
+	}
+
+	/* Verify that gamemode is now innactive */
+	if (verify_deactivated() != 0)
+		return -1;
+
+	/* Try running some process interop tests */
+	fprintf(stdout, "running tests with two clients...\n");
+
+	/* Get the current path to this binary */
+	char mypath[PATH_MAX];
+	if (readlink("/proc/self/exe", mypath, PATH_MAX) == -1) {
+		fprintf(stderr, "could not read current exe path\n");
+		return -1;
+	}
+
+	/* Fork so that the child can request gamemode */
+	int child = fork();
+	if (child == 0) {
+		/* Relaunch self with -r (request and wait for signal) */
+		if (execl(mypath, mypath, "-r") == -1) {
+			fprintf(stderr, "failed to re-launch self with execv: %s\n", strerror(errno));
+			return -1;
+		}
+	}
+
+	/* Parent process */
+	/* None of these should early-out as we need to clean up the child */
+
+	/* Give the child a chance to reqeust gamemode */
+	usleep(1000);
+
+	/* Check that when we request gamemode, it replies that the other client is connected */
+	if (verify_other_client_connected() != 0)
+		status = -1;
+
+	/* Verify that gamemode_request_start correctly start gamemode */
+	if (gamemode_request_start() != 0) {
+		fprintf(stderr, "gamemode_request_start failed: %s\n", gamemode_error_string());
+		status = -1;
+	}
+
+	/* Verify that gamemode is now active and this client is registered*/
+	if (verify_active_and_registered() != 0)
+		status = -1;
+
+	/* Send SIGCONT to child */
+	if (kill(child, SIGCONT) == -1) {
+		fprintf(stderr, "failed to send continue signal to other client: %s\n", strerror(errno));
+		return -1;
+	}
+
+	/* Kill the child regardless */
+	if (kill(child, SIGKILL) == -1) {
+		fprintf(stderr, "failed to kill the child: %s\n", strerror(errno));
+		return -1;
+	}
+
+	return status;
+}

+ 1 - 1
daemon/gamemode.h

@@ -135,4 +135,4 @@ char *game_mode_resolve_wine_preloader(const pid_t pid);
 /** gamemode-tests.c
  * Provides a test suite to verify gamemode behaviour
  */
-int game_mode_run_tests(void);
+int game_mode_run_client_tests(void);

+ 1 - 1
daemon/main.c

@@ -142,7 +142,7 @@ int main(int argc, char *argv[])
 			exit(EXIT_SUCCESS);
 			break;
 		case 't':
-			if ((status = game_mode_run_tests()) == 0) {
+			if ((status = game_mode_run_client_tests()) == 0) {
 				fprintf(stdout, "gamemode tests succeeded\n");
 				exit(EXIT_SUCCESS);
 			} else if (status == -1) {