class_docstr: Abstract class for end-to-end tests of one-turn ParlAIChatBlueprint tasks.
class_docstr_tok: ["Abstract","class","for","end-to-end","tests","of","one-turn","ParlAIChatBlueprint","tasks","."]
docstr: Test that the actual agent states match the expected states.
  
  Register mock human agents, request initial data to define the 'inputs' fields
  of the agent states, make the agents have a conversation to define the 'outputs'
  fields of the agent states, and then check that the agent states all match the
  desired agent states.
code: def _test_agent_states(
      self,
      num_agents: int,
      agent_display_ids: Sequence[str],
      agent_messages: List[Sequence[str]],
      form_messages: Sequence[str],
      form_task_data: Sequence[Dict[str, Any]],
      expected_states: Sequence[Dict[str, Any]],
      agent_task_data: Optional[List[Sequence[Dict[str, Any]]]] = None,
  ):
      """
      Test that the actual agent states match the expected states.
  
      Register mock human agents, request initial data to define the 'inputs' fields
      of the agent states, make the agents have a conversation to define the 'outputs'
      fields of the agent states, and then check that the agent states all match the
      desired agent states.
      """
  
      # If no task data was supplied, create empty task data
      if agent_task_data is None:
          agent_task_data = []
          for message_round in agent_messages:
              agent_task_data.append([{}] * len(message_round))
  
      # Set up the mock human agents
      agent_ids = self._register_mock_agents(num_agents=num_agents)
  
      # # Feed messages to the agents
  
      # Have agents talk to each other
      assert len(agent_messages) == len(agent_task_data)
      for message_round, task_data_round in zip(
          agent_messages, agent_task_data
      ):
          assert (
              len(message_round)
              == len(task_data_round)
              == len(agent_ids)
          )
          for agent_id, agent_display_id, message, task_data in zip(
              agent_ids,
              agent_display_ids,
              message_round,
              task_data_round,
          ):
              self._send_agent_message(
                  agent_id=agent_id,
                  agent_display_id=agent_display_id,
                  text=message,
                  task_data=task_data,
              )
  
      # Have agents fill out the form
      for agent_idx, agent_id in enumerate(agent_ids):
          self.server.send_agent_act(
              agent_id=agent_id,
              act_content={
                  "text": form_messages[agent_idx],
                  "task_data": form_task_data[agent_idx],
                  "id": agent_display_ids[agent_idx],
                  "episode_done": False,
              },
          )
          self.await_channel_requests()
  
      # Submit the HIT
      for agent_id in agent_ids:
          self.server.submit_mock_unit(agent_id, {"final_data": {}})
          self.await_channel_requests()
  
      # # Check that the inputs and outputs are as expected
  
      # Get and filter actual messages
      time.sleep(self.message_sleep_time)
      actual_states = [
          agent.state.get_data() for agent in self.db.find_agents()
      ]
      if len(actual_states) != len(expected_states):
          raise ValueError(
              f"There are {len(actual_states):d} agent states, instead of {len(expected_states):d} as expected!"
          )
      filtered_actual_states = []
      for actual_state in actual_states:
          filtered_actual_states.append(
              self._filter_agent_state_data(actual_state)
          )
  
      # Check the contents of each message
      for actual_state, expected_state in zip(
          filtered_actual_states, expected_states
      ):
          clean_actual_state = self._remove_non_deterministic_keys(
              actual_state
          )
          assert (
              clean_actual_state["inputs"] == expected_state["inputs"]
          )
          actual_num_messages = len(
              clean_actual_state["outputs"]["messages"]
          )
          expected_num_messages = len(
              expected_state["outputs"]["messages"]
          )
          if actual_num_messages != expected_num_messages:
              raise ValueError(
                  f"The actual number of messages is {actual_num_messages:d}, instead of {expected_num_messages:d} as expected!"
              )
          for actual_message, expected_message in zip(
              clean_actual_state["outputs"]["messages"],
              expected_state["outputs"]["messages"],
          ):
              for key, expected_value in expected_message.items():
                  self._check_output_key(
                      key=key,
                      actual_value=actual_message[key],
                      expected_value=expected_value,
                  )
  
imports: import os
  import random
  import tempfile
  import time
  import unittest
  from typing import Any, Dict, List, Optional, Sequence, Union
  import numpy
  import torch
  from parlai.utils import logging
  from hydra.experimental import compose, initialize
  from mephisto.abstractions.blueprint import SharedTaskState
  from mephisto.abstractions.databases.local_database import LocalMephistoDB
  from mephisto.data_model.task_run import TaskRunArgs
  from mephisto.operations.operator import Operator
  from mephisto.tools.scripts import augment_config_from_db
  from mephisto.utils.metrics import InaccessiblePrometheusServer
  from pytest_regressions.data_regression import DataRegressionFixture
label_desc: Use image node_id 2 for calling the AbstractParlAIChatTest obj's underlying member method code with example usage: obj._test_agent_states(num_agents, agent_display_ids, agent_messages, form_messages, form_task_data, expected_states, agent_task_data) without return types