Esempio n. 1
0
class TestCaseBase(unittest.TestCase):

	def setUp(self):
		self.mod_tessumod = None
		self.ts_client_query_server = None
		self.__ts_plugin_info = None
		self.event_loop = EventLoop()
		self.__verifiers = []
		self.__max_end_time = None
		self.__min_end_time = None
		self.__event_handlers = {}

		shutil.rmtree(TMP_DIRPATH, ignore_errors=True)

		if FAKES_DIRPATH not in sys.path:
			sys.path.append(FAKES_DIRPATH)
		if MOD_SCRIPTS_DIRPATH not in sys.path:
			sys.path.append(MOD_SCRIPTS_DIRPATH)

		os.makedirs(MODS_VERSION_DIRPATH)

		shutil.copytree(os.path.join(MOD_SRC_DIRPATH, "gui"), os.path.join(MODS_VERSION_DIRPATH, "gui"))

		import ResMgr
		ResMgr.RES_MODS_VERSION_PATH = MODS_VERSION_DIRPATH

		mod_settings.INI_DIRPATH = INI_DIRPATH
		mod_settings.reset_cache_file()
		mod_settings.reset_settings_file()
		self.change_mod_settings(
			General = {
				# "log_level": "0", # enable for debug logging
				"speak_stop_delay": "0" # makes tests execute faster
			},
			TSClientQueryService = {
				"polling_interval": "0" # makes tests execute faster
			}
		)
		# create empty ts plugin installer file
		open(TS_PLUGIN_INSTALLER_PATH, "w").close()

	def tearDown(self):
		if self.__ts_plugin_info:
			self.__ts_plugin_info.close()
		if self.ts_client_query_server:
			self.ts_client_query_server.stop()
		sys.path.remove(FAKES_DIRPATH)
		sys.path.remove(MOD_SCRIPTS_DIRPATH)

	def start_ts_client(self, **state):
		assert self.ts_client_query_server == None, "Cannot start TS client if it is already running"
		self.ts_client_query_server = TSClientQueryService()
		self.ts_client_query_server.start()
		self.change_ts_client_state(**state)

	def enable_ts_client_tessumod_plugin(self, version=0):
		self.__ts_plugin_info = mmap.mmap(0, 1, "TessuModTSPluginInfo", mmap.ACCESS_WRITE)
		self.__ts_plugin_info.write(struct.pack("=B", version))

	def get_shared_memory_contents(self, memory):
		assert memory == "TessuModTSPlugin3dAudio" # currently this is only memory supported
		shmem = mmap.mmap(0, 1024, memory, mmap.ACCESS_READ)
		(
			timestamp,
			camera_pos_x,
			camera_pos_y,
			camera_pos_z,
			camera_dir_x,
			camera_dir_y,
			camera_dir_z,
			client_count
		) = struct.unpack("=I3f3fB", shmem.read(4+3*4+3*4+1))
		clients = {}
		for client_index in range(0, client_count):
			client_id, x, y, z = struct.unpack("=h3f", shmem.read(2+3*4))
			clients[self.ts_client_query_server.get_user(clid=client_id).name] = {
				"position": (x, y, z)
			}

		return {
			"timestamp": timestamp,
			"camera": {
				"position": (camera_pos_x, camera_pos_y, camera_pos_z),
				"direction": (camera_dir_x, camera_dir_y, camera_dir_z)
			},
			"clients": clients
		}

	def on_event(self, name, callback):
		def call_wrapper(callback, *args, **kwargs):
			callback()
		wrapped_callback = partial(call_wrapper, callback)
		if not self.__install_event_handler(name, wrapped_callback):
			if name not in self.__event_handlers:
				self.__event_handlers[name] = []
			self.__event_handlers[name].append(wrapped_callback)

	def __install_event_handler(self, name, callback):
		if self.mod_tessumod is not None:
			cq = sys.modules["tessumod.infrastructure.di"].get_provided("chatclient").get_clientquery()
			if name == "on_connected_to_ts_server":
				cq.on("connected-server-name", callback)
			elif name == "on_connected_to_ts_client":
				cq.on("connected", callback)
			elif name == "on_disconnected_from_ts_client":
				cq.on("disconnected", callback)
			else:
				raise RuntimeError("No such event: {0}".format(name))
			return True
		return False

	def start_game(self, **game_state):
		import mod_tessumod
		self.mod_tessumod = mod_tessumod
		self.mod_tessumod.init()

		for name, callbacks in self.__event_handlers.iteritems():
			for callback in callbacks:
				self.__install_event_handler(name, callback)

		self.change_game_state(**game_state)

	def run_in_event_loop(self, timeout=20):
		self.event_loop.call(self.__on_loop, repeat=True, timeout=0.05)
		self.event_loop.call(self.__check_verify, repeat=True, timeout=1)
		self.__max_end_time = time.time() + timeout
		if self.__min_end_time is None:
			self.__min_end_time = time.time()
		self.event_loop.execute()

	def change_ts_client_state(self, **state):
		assert self.ts_client_query_server, "TS client must be running to change its state"
		if "running" in state:
			if not state["running"]:
				self.ts_client_query_server.stop()
				self.ts_client_query_server = None
		if "connected_to_server" in state:
			self.ts_client_query_server.set_connected_to_server(state["connected_to_server"])
		if "users" in state:
			for name, data in state["users"].iteritems():
				self.ts_client_query_server.set_user(name, **data)

	def change_game_state(self, **state):
		import BigWorld, Avatar, Account
		assert self.mod_tessumod, "Mod must be loaded first before changing game state"

		if state["mode"] == "battle":
			BigWorld.player(Avatar.Avatar())
			if "players" in state:
				for player in state["players"]:
					vehicle_id = random.randint(0, 1000000)
					dbid = random.randint(0, 1000000)
					BigWorld.player().arena.vehicles[vehicle_id] = {
						"accountDBID": dbid,
						"name":        player["name"],
						"isAlive":     True
					}
					if vehicle_id not in BigWorld.entities:
						BigWorld.entities[vehicle_id] = BigWorld.Entity()
					if "position" in player:
						BigWorld.player().arena.positions[vehicle_id] = player["position"]
						BigWorld.entities[vehicle_id].position = BigWorld.Vector(*player["position"])
			if "camera" in state:
				if "position" in state["camera"]:
					BigWorld.camera().position = BigWorld.Vector(*state["camera"]["position"])
				if "direction" in state["camera"]:
					BigWorld.camera().direction = BigWorld.Vector(*state["camera"]["direction"])
		elif state["mode"] == "lobby":
			BigWorld.player(Account.PlayerAccount())
			if "players" in state:
				for id, player in enumerate(state["players"]):
					BigWorld.player().prebattle.rosters[0][id] = {
						"name": player["name"],
						"dbID": random.randint(0, 1000000)
					}

	def get_player_id(self, name):
		import BigWorld
		if hasattr(BigWorld.player(), "arena"):
			for vehicle in BigWorld.player().arena.vehicles.itervalues():
				if vehicle["name"] == name:
					return vehicle["accountDBID"]

	def get_vehicle_id(self, name):
		import BigWorld
		if hasattr(BigWorld.player(), "arena"):
			for vehicle_id, vehicle in BigWorld.player().arena.vehicles.iteritems():
				if vehicle["name"] == name:
					return vehicle_id

	def change_mod_settings(self, **groups):
		for group_name, variables in groups.iteritems():
			for var_name, var_value in variables.iteritems():
				mod_settings.set_setting(group_name, var_name, var_value)

	def change_mod_user_cache(self, **groups):
		for group_name, variables in groups.iteritems():
			for var_name, var_value in variables.iteritems():
				mod_settings.set_cache_entry(group_name, var_name, var_value)

	def change_mod_state_variables(self, **variables):
		states_dirpath = os.path.join(INI_DIRPATH, "states")
		if not os.path.exists(states_dirpath):
			os.makedirs(states_dirpath)
		for key, value in variables.iteritems():
			with open(os.path.join(states_dirpath, key), "w") as file:
				file.write(json.dumps(value))

	def get_mod_state_variable(self, key):
		states_dirpath = os.path.join(INI_DIRPATH, "states")
		key_path = os.path.join(states_dirpath, key)
		if os.path.exists(key_path):
			with open(key_path, "r") as file:
				return json.loads(file.read())

	def call_later(self, callback, timeout=0):
		self.event_loop.call(callback, timeout=timeout)

	def __on_loop(self):
		import BigWorld
		BigWorld.tick()
		if self.ts_client_query_server:
			self.ts_client_query_server.check()
		self.assertLess(time.time(), self.__max_end_time, "Execution took too long")

	def __check_verify(self):
		try:
			if time.time() >= self.__min_end_time and all(verifier() for verifier in self.__verifiers):
				self.event_loop.exit()
		except Exception as error:
			print "{0} in __check_verify: {1}".format(error.__class__.__name__, error)

	def assert_finally_equal(self, a, b):
		actual_getter = a if callable(a) else b
		expected = b if callable(a) else a
		self.__verifiers.append(lambda: actual_getter() == expected)

	def assert_finally_true(self, x):
		self.__verifiers.append(x)

	def assert_finally_false(self, x):
		self.__verifiers.append(lambda: not x())

	def wait_at_least(self, secs):
		self.__min_end_time = time.time() + secs
Esempio n. 2
0
class TestCaseBase(unittest.TestCase):
    def setUp(self):
        self.mod_tessumod = None
        self.ts_client_query_server = None
        self.__ts_plugin_info = None
        self.event_loop = EventLoop()
        self.__verifiers = []
        self.__max_end_time = None
        self.__min_end_time = None
        self.__event_handlers = {}

        shutil.rmtree(TMP_DIRPATH, ignore_errors=True)

        if FAKES_DIRPATH not in sys.path:
            sys.path.append(FAKES_DIRPATH)
        if MOD_SCRIPTS_DIRPATH not in sys.path:
            sys.path.append(MOD_SCRIPTS_DIRPATH)

        os.makedirs(MODS_VERSION_DIRPATH)

        shutil.copytree(os.path.join(MOD_SRC_DIRPATH, "gui"),
                        os.path.join(MODS_VERSION_DIRPATH, "gui"))

        import ResMgr
        ResMgr.RES_MODS_VERSION_PATH = MODS_VERSION_DIRPATH

        mod_settings.INI_DIRPATH = INI_DIRPATH
        mod_settings.reset_cache_file()
        mod_settings.reset_settings_file()
        self.change_mod_settings(
            General={
                # "log_level": "0", # enable for debug logging
                "speak_stop_delay": "0"  # makes tests execute faster
            },
            TSClientQueryService={
                "polling_interval": "0"  # makes tests execute faster
            })
        # create empty ts plugin installer file
        open(TS_PLUGIN_INSTALLER_PATH, "w").close()

    def tearDown(self):
        if self.__ts_plugin_info:
            self.__ts_plugin_info.close()
        if self.ts_client_query_server:
            self.ts_client_query_server.stop()
        sys.path.remove(FAKES_DIRPATH)
        sys.path.remove(MOD_SCRIPTS_DIRPATH)

    def start_ts_client(self, **state):
        assert self.ts_client_query_server == None, "Cannot start TS client if it is already running"
        self.ts_client_query_server = TSClientQueryService()
        self.ts_client_query_server.start()
        self.change_ts_client_state(**state)

    def enable_ts_client_tessumod_plugin(self, version=0):
        self.__ts_plugin_info = mmap.mmap(0, 1, "TessuModTSPluginInfo",
                                          mmap.ACCESS_WRITE)
        self.__ts_plugin_info.write(struct.pack("=B", version))

    def get_shared_memory_contents(self, memory):
        assert memory == "TessuModTSPlugin3dAudio"  # currently this is only memory supported
        shmem = mmap.mmap(0, 1024, memory, mmap.ACCESS_READ)
        (timestamp, camera_pos_x, camera_pos_y, camera_pos_z, camera_dir_x,
         camera_dir_y, camera_dir_z,
         client_count) = struct.unpack("=I3f3fB",
                                       shmem.read(4 + 3 * 4 + 3 * 4 + 1))
        clients = {}
        for client_index in range(0, client_count):
            client_id, x, y, z = struct.unpack("=h3f", shmem.read(2 + 3 * 4))
            clients[self.ts_client_query_server.get_user(
                clid=client_id).name] = {
                    "position": (x, y, z)
                }

        return {
            "timestamp": timestamp,
            "camera": {
                "position": (camera_pos_x, camera_pos_y, camera_pos_z),
                "direction": (camera_dir_x, camera_dir_y, camera_dir_z)
            },
            "clients": clients
        }

    def on_event(self, name, callback):
        def call_wrapper(callback, *args, **kwargs):
            callback()

        wrapped_callback = partial(call_wrapper, callback)
        if not self.__install_event_handler(name, wrapped_callback):
            if name not in self.__event_handlers:
                self.__event_handlers[name] = []
            self.__event_handlers[name].append(wrapped_callback)

    def __install_event_handler(self, name, callback):
        if self.mod_tessumod is not None:
            cq = sys.modules["tessumod.infrastructure.di"].get_provided(
                "chatclient").get_clientquery()
            if name == "on_connected_to_ts_server":
                cq.on("connected-server-name", callback)
            elif name == "on_connected_to_ts_client":
                cq.on("connected", callback)
            elif name == "on_disconnected_from_ts_client":
                cq.on("disconnected", callback)
            else:
                raise RuntimeError("No such event: {0}".format(name))
            return True
        return False

    def start_game(self, **game_state):
        import mod_tessumod
        self.mod_tessumod = mod_tessumod
        self.mod_tessumod.init()

        for name, callbacks in self.__event_handlers.iteritems():
            for callback in callbacks:
                self.__install_event_handler(name, callback)

        self.change_game_state(**game_state)

    def run_in_event_loop(self, timeout=20):
        self.event_loop.call(self.__on_loop, repeat=True, timeout=0.05)
        self.event_loop.call(self.__check_verify, repeat=True, timeout=1)
        self.__max_end_time = time.time() + timeout
        if self.__min_end_time is None:
            self.__min_end_time = time.time()
        self.event_loop.execute()

    def change_ts_client_state(self, **state):
        assert self.ts_client_query_server, "TS client must be running to change its state"
        if "running" in state:
            if not state["running"]:
                self.ts_client_query_server.stop()
                self.ts_client_query_server = None
        if "connected_to_server" in state:
            self.ts_client_query_server.set_connected_to_server(
                state["connected_to_server"])
        if "users" in state:
            for name, data in state["users"].iteritems():
                self.ts_client_query_server.set_user(name, **data)

    def change_game_state(self, **state):
        import BigWorld, Avatar, Account
        assert self.mod_tessumod, "Mod must be loaded first before changing game state"

        if state["mode"] == "battle":
            BigWorld.player(Avatar.Avatar())
            if "players" in state:
                for player in state["players"]:
                    vehicle_id = random.randint(0, 1000000)
                    dbid = random.randint(0, 1000000)
                    BigWorld.player().arena.vehicles[vehicle_id] = {
                        "accountDBID": dbid,
                        "name": player["name"],
                        "isAlive": True
                    }
                    if vehicle_id not in BigWorld.entities:
                        BigWorld.entities[vehicle_id] = BigWorld.Entity()
                    if "position" in player:
                        BigWorld.player(
                        ).arena.positions[vehicle_id] = player["position"]
                        BigWorld.entities[
                            vehicle_id].position = BigWorld.Vector(
                                *player["position"])
            if "camera" in state:
                if "position" in state["camera"]:
                    BigWorld.camera().position = BigWorld.Vector(
                        *state["camera"]["position"])
                if "direction" in state["camera"]:
                    BigWorld.camera().direction = BigWorld.Vector(
                        *state["camera"]["direction"])
        elif state["mode"] == "lobby":
            BigWorld.player(Account.PlayerAccount())
            if "players" in state:
                for id, player in enumerate(state["players"]):
                    BigWorld.player().prebattle.rosters[0][id] = {
                        "name": player["name"],
                        "dbID": random.randint(0, 1000000)
                    }

    def get_player_id(self, name):
        import BigWorld
        if hasattr(BigWorld.player(), "arena"):
            for vehicle in BigWorld.player().arena.vehicles.itervalues():
                if vehicle["name"] == name:
                    return vehicle["accountDBID"]

    def get_vehicle_id(self, name):
        import BigWorld
        if hasattr(BigWorld.player(), "arena"):
            for vehicle_id, vehicle in BigWorld.player(
            ).arena.vehicles.iteritems():
                if vehicle["name"] == name:
                    return vehicle_id

    def change_mod_settings(self, **groups):
        for group_name, variables in groups.iteritems():
            for var_name, var_value in variables.iteritems():
                mod_settings.set_setting(group_name, var_name, var_value)

    def change_mod_user_cache(self, **groups):
        for group_name, variables in groups.iteritems():
            for var_name, var_value in variables.iteritems():
                mod_settings.set_cache_entry(group_name, var_name, var_value)

    def change_mod_state_variables(self, **variables):
        states_dirpath = os.path.join(INI_DIRPATH, "states")
        if not os.path.exists(states_dirpath):
            os.makedirs(states_dirpath)
        for key, value in variables.iteritems():
            with open(os.path.join(states_dirpath, key), "w") as file:
                file.write(json.dumps(value))

    def get_mod_state_variable(self, key):
        states_dirpath = os.path.join(INI_DIRPATH, "states")
        key_path = os.path.join(states_dirpath, key)
        if os.path.exists(key_path):
            with open(key_path, "r") as file:
                return json.loads(file.read())

    def call_later(self, callback, timeout=0):
        self.event_loop.call(callback, timeout=timeout)

    def __on_loop(self):
        import BigWorld
        BigWorld.tick()
        if self.ts_client_query_server:
            self.ts_client_query_server.check()
        self.assertLess(time.time(), self.__max_end_time,
                        "Execution took too long")

    def __check_verify(self):
        try:
            if time.time() >= self.__min_end_time and all(
                    verifier() for verifier in self.__verifiers):
                self.event_loop.exit()
        except Exception as error:
            print "{0} in __check_verify: {1}".format(error.__class__.__name__,
                                                      error)

    def assert_finally_equal(self, a, b):
        actual_getter = a if callable(a) else b
        expected = b if callable(a) else a
        self.__verifiers.append(lambda: actual_getter() == expected)

    def assert_finally_true(self, x):
        self.__verifiers.append(x)

    def assert_finally_false(self, x):
        self.__verifiers.append(lambda: not x())

    def wait_at_least(self, secs):
        self.__min_end_time = time.time() + secs