def apply(self): try: if self.agent_id != self._replay.agent_id: raise ReplayError( "Tried to apply the entry belonging to the " "agent id: %r, but the Replay instance " "belogs to: %r" % (self.agent_id, self._replay.agent_id) ) self._replay.set_current_time(self._timestamp) if self.journal_id == "agency": self._replay.replay_agency_entry(self) return self self._replay._log_entry(self) self._replay.require_agent() instance = self._replay.registry.get(self.journal_id, None) if instance is None: raise ReplayError( "Instance for journal_id %r not found " "in the registry when replaying %r" % (self.journal_id, self.function_id) ) result = instance.replay(self) if self._next_effect < len(self._side_effects): remaining = self._side_effects[self._next_effect] side_effect = self.restore_side_effect(remaining, parse_args=True) function_id, args, kwargs, _effects, _result = side_effect se_desc = side_effect_as_string(function_id, args, kwargs) raise ReplayError("Function %s did not consume side-effect %s" % (self.function_id, se_desc)) frozen_result = self._replay.serializer.freeze(result) unfrozen_result = self._replay.unserializer.convert(frozen_result) expected = self._replay.unserializer.convert(self.frozen_result) if unfrozen_result != expected: res = pformat(unfrozen_result) exp = pformat(expected) diffs = text_helper.format_diff(exp, res, "\n ") raise ReplayError( "Function %r replay result " "does not match recorded one.\n" " RESULT: %s\n" " EXPECTED: %s\n" " DIFFERENCES: %s\n" % (self.function_id, res, exp, diffs) ) self._replay.log("State after the entry: %r", self._replay.agent._get_state()) return self except Exception as e: error.handle_exception( "replay", e, "Failed trying to apply instance %r entry %r: ", self.journal_id, self.function_id ) raise
def _validate_replay_on_agent(self, history, entries): aid = history.agent_id agent = yield self.driver.find_agent(aid) if agent is None: self.warning( 'Agent with id %r not found. ' 'This usually means it was terminated, during the test.', aid) return if agent._instance_id != history.instance_id: self.warning( 'Agent instance id is %s, the journal entries are for ' 'instance_id %s. This history will not get validated, as ' 'now we dont have the real instance to compare the result ' 'with.', agent._instance_id, history.instance_id) return self.log("Validating replay of %r with id: %s", agent.agent.__class__.__name__, aid) self.log("Found %d entries of this agent.", len(entries)) r = replay.Replay(iter(entries), aid) for entry in r: entry.apply() agent_snapshot, protocols = agent.snapshot_agent() self.log("Replay complete. Comparing state of the agent and his " "%d protocols.", len(protocols)) if agent_snapshot._get_state() != r.agent._get_state(): s1 = r.agent._get_state() s2 = agent_snapshot._get_state() comp = self.deep_compare(s1, s2) info = " INFO: %s: %s\n" % comp if comp else "" res = repr(pytree.serialize(agent_snapshot._get_state())) exp = repr(pytree.serialize(r.agent._get_state())) diffs = text_helper.format_diff(exp, res, "\n ") self.fail("Agent snapshot different after replay:\n%s" " SNAPSHOT: %s\n" " EXPECTED: %s\n" " DIFFERENCES: %s\n" % (info, res, exp, diffs)) self.assertEqual(agent_snapshot._get_state(), r.agent._get_state()) self.assertEqual(len(r.protocols), len(protocols), "Protocols of agent: %s from replay doesn't much " "the test result. \nReplay: %s,\nResult: %s" % (aid, pformat(r.protocols), pformat(protocols))) def sort(recorders): # at some point the protocols are stored as the dictionary values, # for this reason they come in snapshot in random order and need # to be sorted before comparing return sorted(recorders, key=operator.attrgetter('journal_id')) for from_snapshot, from_replay in zip(sort(protocols), sort(r.protocols)): self.assertEqual(from_snapshot._get_state(), from_replay._get_state(), "Failed comparing state of protocols. \nA=%s " "\B=%s." % (pformat(from_snapshot), pformat(from_replay)))