# Copyright 2017 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging

from collections import defaultdict
from enum import Enum
from mobly import base_test
from mobly import records
from mobly import signals
from mobly import utils


class _InstrumentationStructurePrefixes(object):
  """Class containing prefixes that structure insturmentation output.

  Android instrumentation generally follows the following format:

  .. code-block:: none

    INSTRUMENTATION_STATUS: ...
    ...
    INSTRUMENTATION_STATUS: ...
    INSTRUMENTATION_STATUS_CODE: ...
    INSTRUMENTATION_STATUS: ...
    ...
    INSTRUMENTATION_STATUS: ...
    INSTRUMENTATION_STATUS_CODE: ...
    ...
    INSTRUMENTATION_RESULT: ...
    ...
    INSTRUMENTATION_RESULT: ...
    ...
    INSTRUMENTATION_CODE: ...

  This means that these prefixes can be used to guide parsing
  the output of the instrumentation command into the different
  instrumetnation test methods.

  Refer to the following Android Framework package for more details:

  .. code-block:: none

    com.android.commands.am.AM

  """

  STATUS = 'INSTRUMENTATION_STATUS:'
  STATUS_CODE = 'INSTRUMENTATION_STATUS_CODE:'
  RESULT = 'INSTRUMENTATION_RESULT:'
  CODE = 'INSTRUMENTATION_CODE:'
  FAILED = 'INSTRUMENTATION_FAILED:'


class _InstrumentationKnownStatusKeys(object):
  """Commonly used keys used in instrumentation output for listing
  instrumentation test method result properties.

  An instrumenation status line usually contains a key-value pair such as
  the following:

  .. code-block:: none

    INSTRUMENTATION_STATUS: <key>=<value>

  Some of these key-value pairs are very common and represent test case
  properties. This mapping is used to handle each of the corresponding
  key-value pairs different than less important key-value pairs.

  Refer to the following Android Framework packages for more details:

  .. code-block:: none

    android.app.Instrumentation
    android.support.test.internal.runner.listener.InstrumentationResultPrinter

  TODO: Convert android.support.* to androidx.*,
  (https://android-developers.googleblog.com/2018/05/hello-world-androidx.html).
  """

  CLASS = 'class'
  ERROR = 'Error'
  STACK = 'stack'
  TEST = 'test'
  STREAM = 'stream'


class _InstrumentationStatusCodes(object):
  """A mapping of instrumentation status codes to test method results.

  When instrumentation runs, at various points output is created in a series
  of blocks that terminate as follows:

  .. code-block:: none

    INSTRUMENTATION_STATUS_CODE: 1

  These blocks typically have several status keys in them, and they indicate
  the progression of a particular instrumentation test method. When the
  corresponding instrumentation test method finishes, there is generally a
  line which includes a status code that gives thes the test result.

  The UNKNOWN status code is not an actual status code and is only used to
  represent that a status code has not yet been read for an instrumentation
  block.

  Refer to the following Android Framework package for more details:

  .. code-block:: none

    android.support.test.internal.runner.listener.InstrumentationResultPrinter

  TODO: Convert android.support.* to androidx.*,
  (https://android-developers.googleblog.com/2018/05/hello-world-androidx.html).
  """

  UNKNOWN = None
  OK = '0'
  START = '1'
  IN_PROGRESS = '2'
  ERROR = '-1'
  FAILURE = '-2'
  IGNORED = '-3'
  ASSUMPTION_FAILURE = '-4'


class _InstrumentationStatusCodeCategories(object):
  """A mapping of instrumentation test method results to categories.

  Aside from the TIMING category, these categories roughly map to Mobly
  signals and are used for determining how a particular instrumentation test
  method gets recorded.
  """

  TIMING = [
      _InstrumentationStatusCodes.START,
      _InstrumentationStatusCodes.IN_PROGRESS,
  ]
  PASS = [
      _InstrumentationStatusCodes.OK,
  ]
  FAIL = [
      _InstrumentationStatusCodes.ERROR,
      _InstrumentationStatusCodes.FAILURE,
  ]
  SKIPPED = [
      _InstrumentationStatusCodes.IGNORED,
      _InstrumentationStatusCodes.ASSUMPTION_FAILURE,
  ]


class _InstrumentationKnownResultKeys(object):
  """Commonly used keys for outputting instrumentation errors.

  When instrumentation finishes running all of the instrumentation test
  methods, a result line will appear as follows:

  .. code-block:: none

    INSTRUMENTATION_RESULT:

  If something wrong happened during the instrumentation run such as an
  application under test crash, the line will appear similarly as thus:

  .. code-block:: none

    INSTRUMENTATION_RESULT: shortMsg=Process crashed.

  Since these keys indicate that something wrong has happened to the
  instrumentation run, they should be checked for explicitly.

  Refer to the following documentation page for more information:

  .. code-block:: none

    https://developer.android.com/reference/android/app/ActivityManager.ProcessErrorStateInfo.html

  """

  LONGMSG = 'longMsg'
  SHORTMSG = 'shortMsg'


class _InstrumentationResultSignals(object):
  """Instrumenttion result block strings for signalling run completion.

  The final section of the instrumentation output generally follows this
  format:

  .. code-block:: none

    INSTRUMENTATION_RESULT: stream=
    ...
    INSTRUMENTATION_CODE -1

  Inside of the ellipsed section, one of these signaling strings should be
  present. If they are not present, this usually means that the
  instrumentation run has failed in someway such as a crash. Because the
  final instrumentation block simply summarizes information, simply roughly
  checking for a particilar string should be sufficient to check to a proper
  run completion as the contents of the instrumentation result block don't
  really matter.

  Refer to the following JUnit package for more details:

  .. code-block:: none

    junit.textui.ResultPrinter

  """

  FAIL = 'FAILURES!!!'
  PASS = 'OK ('


class _InstrumentationBlockStates(Enum):
  """States used for determing what the parser is currently parsing.

  The parse always starts and ends a block in the UNKNOWN state, which is
  used to indicate that either a method or a result block (matching the
  METHOD and RESULT states respectively) are valid follow ups, which means
  that parser should be checking for a structure prefix that indicates which
  of those two states it should transition to. If the parser is in the
  METHOD state, then the parser will be parsing input into test methods.
  Otherwise, the parse can simply concatenate all the input to check for
  some final run completion signals.
  """

  UNKNOWN = 0
  METHOD = 1
  RESULT = 2


class _InstrumentationBlock(object):
  """Container class for parsed instrumentation output for instrumentation
  test methods.

  Instrumentation test methods typically follow the follwoing format:

  .. code-block:: none

    INSTRUMENTATION_STATUS: <key>=<value>
    ...
    INSTRUMENTATION_STATUS: <key>=<value>
    INSTRUMENTATION_STATUS_CODE: <status code #>

  The main issue with parsing this however is that the key-value pairs can
  span multiple lines such as this:

  .. code-block:: none

    INSTRUMENTATION_STATUS: stream=
    Error in ...
    ...

  Or, such as this:

  .. code-block:: none

    INSTRUMENTATION_STATUS: stack=...
    ...

  Because these keys are poentially very long, constant string contatention
  is potentially inefficent. Instead, this class builds up a buffer to store
  the raw output until it is processed into an actual test result by the
  _InstrumentationBlockFormatter class.

  Additionally, this class also serves to store the parser state, which
  means that the BaseInstrumentationTestClass does not need to keep any
  potentially volatile instrumentation related state, so multiple
  instrumentation runs should have completely separate parsing states.

  This class is also used for storing result blocks although very little
  needs to be done for those.

  Attributes:
    begin_time: string, optional timestamp for when the test corresponding
      to the instrumentation block began.
    current_key: string, the current key that is being parsed, default to
      _InstrumentationKnownStatusKeys.STREAM.
    error_message: string, an error message indicating that something
      unexpected happened during a instrumentatoin test method.
    known_keys: dict, well known keys that are handled uniquely.
    prefix: string, a prefix to add to the class name of the
      instrumentation test methods.
    previous_instrumentation_block: _InstrumentationBlock, the last parsed
      instrumentation block.
    state: _InstrumentationBlockStates, the current state of the parser.
    status_code: string, the state code for an instrumentation method
      block.
    unknown_keys: dict, arbitrary keys that are handled generically.
  """

  def __init__(self,
               state=_InstrumentationBlockStates.UNKNOWN,
               prefix=None,
               previous_instrumentation_block=None):
    self.state = state
    self.prefix = prefix
    self.previous_instrumentation_block = previous_instrumentation_block
    if previous_instrumentation_block:
      # The parser never needs lookback for two previous blocks,
      # so unset to allow previous blocks to get garbage collected.
      previous_instrumentation_block.previous_instrumentation_block = None

    self._empty = True
    self.error_message = ''
    self.status_code = _InstrumentationStatusCodes.UNKNOWN

    self.current_key = _InstrumentationKnownStatusKeys.STREAM
    self.known_keys = {
        _InstrumentationKnownStatusKeys.STREAM: [],
        _InstrumentationKnownStatusKeys.CLASS: [],
        _InstrumentationKnownStatusKeys.ERROR: [],
        _InstrumentationKnownStatusKeys.STACK: [],
        _InstrumentationKnownStatusKeys.TEST: [],
        _InstrumentationKnownResultKeys.LONGMSG: [],
        _InstrumentationKnownResultKeys.SHORTMSG: [],
    }
    self.unknown_keys = defaultdict(list)

    self.begin_time = None

  @property
  def is_empty(self):
    """Deteremines whether or not anything has been parsed with this
    instrumentation block.

    Returns:
      A boolean indicating whether or not the this instrumentation block
      has parsed and contains any output.
    """
    return self._empty

  def set_error_message(self, error_message):
    """Sets an error message on an instrumentation block.

    This method is used exclusively to indicate that a test method failed
    to complete, which is usually cause by a crash of some sort such that
    the test method is marked as error instead of ignored.

    Args:
      error_message: string, an error message to be added to the
        TestResultRecord to explain that something wrong happened.
    """
    self._empty = False
    self.error_message = error_message

  def _remove_structure_prefix(self, prefix, line):
    """Helper function for removing the structure prefix for parsing.

    Args:
      prefix: string, a _InstrumentationStructurePrefixes to remove from
        the raw output.
      line: string, the raw line from the instrumentation output.

    Returns:
      A string containing a key value pair descripting some property
      of the current instrumentation test method.
    """
    return line[len(prefix):].strip()

  def set_status_code(self, status_code_line):
    """Sets the status code for the instrumentation test method, used in
    determining the test result.

    Args:
      status_code_line: string, the raw instrumentation output line that
        contains the status code of the instrumentation block.
    """
    self._empty = False
    self.status_code = self._remove_structure_prefix(
        _InstrumentationStructurePrefixes.STATUS_CODE,
        status_code_line,
    )
    if self.status_code == _InstrumentationStatusCodes.START:
      self.begin_time = utils.get_current_epoch_time()

  def set_key(self, structure_prefix, key_line):
    """Sets the current key for the instrumentation block.

    For unknown keys, the key is added to the value list in order to
    better contextualize the value in the output.

    Args:
      structure_prefix: string, the structure prefix that was matched
        and that needs to be removed.
      key_line: string, the raw instrumentation output line that contains
        the key-value pair.
    """
    self._empty = False
    key_value = self._remove_structure_prefix(
        structure_prefix,
        key_line,
    )
    if '=' in key_value:
      (key, value) = key_value.split('=', 1)
      self.current_key = key
      if key in self.known_keys:
        self.known_keys[key].append(value)
      else:
        self.unknown_keys[key].append(key_value)

  def add_value(self, line):
    """Adds unstructured or multi-line value output to the current parsed
    instrumentation block for outputting later.

    Usually, this will add extra lines to the value list for the current
    key-value pair. However, sometimes, such as when instrumentation
    failed to start, output does not follow the structured prefix format.
    In this case, adding all of the output is still useful so that a user
    can debug the issue.

    Args:
      line: string, the raw instrumentation line to append to the value
        list.
    """
    # Don't count whitespace only lines.
    if line.strip():
      self._empty = False

    if self.current_key in self.known_keys:
      self.known_keys[self.current_key].append(line)
    else:
      self.unknown_keys[self.current_key].append(line)

  def transition_state(self, new_state):
    """Transitions or sets the current instrumentation block to the new
    parser state.

    Args:
      new_state: _InstrumentationBlockStates, the state that the parser
        should transition to.

    Returns:
      A new instrumentation block set to the new state, representing
      the start of parsing a new instrumentation test method.
      Alternatively, if the current instrumentation block represents the
      start of parsing a new instrumentation block (state UNKNOWN), then
      this returns the current instrumentation block set to the now
      known parsing state.
    """
    if self.state == _InstrumentationBlockStates.UNKNOWN:
      self.state = new_state
      return self
    else:
      next_block = _InstrumentationBlock(
          state=new_state,
          prefix=self.prefix,
          previous_instrumentation_block=self,
      )
      if self.status_code in _InstrumentationStatusCodeCategories.TIMING:
        next_block.begin_time = self.begin_time
      return next_block


class _InstrumentationBlockFormatter(object):
  """Takes an instrumentation block and converts it into a Mobly test
  result.
  """

  DEFAULT_INSTRUMENTATION_METHOD_NAME = 'instrumentation_method'

  def __init__(self, instrumentation_block):
    self._prefix = instrumentation_block.prefix
    self._status_code = instrumentation_block.status_code
    self._error_message = instrumentation_block.error_message
    self._known_keys = {}
    self._unknown_keys = {}
    for key, value in instrumentation_block.known_keys.items():
      self._known_keys[key] = '\n'.join(
          instrumentation_block.known_keys[key]).rstrip()
    for key, value in instrumentation_block.unknown_keys.items():
      self._unknown_keys[key] = '\n'.join(
          instrumentation_block.unknown_keys[key]).rstrip()
    self._begin_time = instrumentation_block.begin_time

  def _get_name(self):
    """Gets the method name of the test method for the instrumentation
    method block.

    Returns:
      A string containing the name of the instrumentation test method's
      test or a default name if no name was parsed.
    """
    if self._known_keys[_InstrumentationKnownStatusKeys.TEST]:
      return self._known_keys[_InstrumentationKnownStatusKeys.TEST]
    else:
      return self.DEFAULT_INSTRUMENTATION_METHOD_NAME

  def _get_class(self):
    """Gets the class name of the test method for the instrumentation
    method block.

    Returns:
      A string containing the class name of the instrumentation test
      method's test or empty string if no name was parsed. If a prefix
      was specified, then the prefix will be prepended to the class
      name.
    """
    class_parts = [
        self._prefix, self._known_keys[_InstrumentationKnownStatusKeys.CLASS]
    ]
    return '.'.join(filter(None, class_parts))

  def _get_full_name(self):
    """Gets the qualified name of the test method corresponding to the
    instrumentation block.

    Returns:
      A string containing the fully qualified name of the
      instrumentation test method. If parts are missing, then degrades
      steadily.
    """
    full_name_parts = [self._get_class(), self._get_name()]
    return '#'.join(filter(None, full_name_parts))

  def _get_details(self):
    """Gets the output for the detail section of the TestResultRecord.

    Returns:
      A string to set for a TestResultRecord's details.
    """
    detail_parts = [self._get_full_name(), self._error_message]
    return '\n'.join(filter(None, detail_parts))

  def _get_extras(self):
    """Gets the output for the extras section of the TestResultRecord.

    Returns:
      A string to set for a TestResultRecord's extras.
    """
    # Add empty line to start key-value pairs on a new line.
    extra_parts = ['']

    for value in self._unknown_keys.values():
      extra_parts.append(value)

    extra_parts.append(self._known_keys[_InstrumentationKnownStatusKeys.STREAM])
    extra_parts.append(
        self._known_keys[_InstrumentationKnownResultKeys.SHORTMSG])
    extra_parts.append(
        self._known_keys[_InstrumentationKnownResultKeys.LONGMSG])
    extra_parts.append(self._known_keys[_InstrumentationKnownStatusKeys.ERROR])

    if self._known_keys[
        _InstrumentationKnownStatusKeys.STACK] not in self._known_keys[
            _InstrumentationKnownStatusKeys.STREAM]:
      extra_parts.append(
          self._known_keys[_InstrumentationKnownStatusKeys.STACK])

    return '\n'.join(filter(None, extra_parts))

  def _is_failed(self):
    """Determines if the test corresponding to the instrumentation block
    failed.

    This method can not be used to tell if a test method passed and
    should not be used for such a purpose.

    Returns:
      A boolean indicating if the test method failed.
    """
    if self._status_code in _InstrumentationStatusCodeCategories.FAIL:
      return True
    elif (self._known_keys[_InstrumentationKnownStatusKeys.STACK] and
          self._status_code != _InstrumentationStatusCodes.ASSUMPTION_FAILURE):
      return True
    elif self._known_keys[_InstrumentationKnownStatusKeys.ERROR]:
      return True
    elif self._known_keys[_InstrumentationKnownResultKeys.SHORTMSG]:
      return True
    elif self._known_keys[_InstrumentationKnownResultKeys.LONGMSG]:
      return True
    else:
      return False

  def create_test_record(self, mobly_test_class):
    """Creates a TestResultRecord for the instrumentation block.

    Args:
      mobly_test_class: string, the name of the Mobly test case
        executing the instrumentation run.

    Returns:
      A TestResultRecord with an appropriate signals exception
      representing the instrumentation test method's result status.
    """
    details = self._get_details()
    extras = self._get_extras()

    tr_record = records.TestResultRecord(
        t_name=self._get_full_name(),
        t_class=mobly_test_class,
    )
    if self._begin_time:
      tr_record.begin_time = self._begin_time

    if self._is_failed():
      tr_record.test_fail(e=signals.TestFailure(details=details, extras=extras))
    elif self._status_code in _InstrumentationStatusCodeCategories.SKIPPED:
      tr_record.test_skip(e=signals.TestSkip(details=details, extras=extras))
    elif self._status_code in _InstrumentationStatusCodeCategories.PASS:
      tr_record.test_pass(e=signals.TestPass(details=details, extras=extras))
    elif self._status_code in _InstrumentationStatusCodeCategories.TIMING:
      if self._error_message:
        tr_record.test_error(
            e=signals.TestError(details=details, extras=extras))
      else:
        tr_record = None
    else:
      tr_record.test_error(e=signals.TestError(details=details, extras=extras))
    if self._known_keys[_InstrumentationKnownStatusKeys.STACK]:
      tr_record.termination_signal.stacktrace = self._known_keys[
          _InstrumentationKnownStatusKeys.STACK]
    return tr_record

  def has_completed_result_block_format(self, error_message):
    """Checks the instrumentation result block for a signal indicating
    normal completion.

    Args:
      error_message: string, the error message to give if the
        instrumentation run did not complete successfully.-

    Returns:
      A boolean indicating whether or not the instrumentation run passed
      or failed overall.

    Raises:
      signals.TestError: Error raised if the instrumentation run did not
        complete because of a crash or some other issue.
    """
    extras = self._get_extras()
    if _InstrumentationResultSignals.PASS in extras:
      return True
    elif _InstrumentationResultSignals.FAIL in extras:
      return False
    else:
      raise signals.TestError(details=error_message, extras=extras)


class InstrumentationTestMixin(object):
  """A mixin for Mobly test classes to inherit from for instrumentation tests.

  This class should be used in a subclass of both BaseTestClass and this class
  in order to provide instrumentation test capabilities. This mixin is
  explicitly for the case where the underlying BaseTestClass cannot be
  replaced with BaseInstrumentationTestClass. In general, prefer using
  BaseInstrumentationTestClass instead.

  Attributes:
    DEFAULT_INSTRUMENTATION_OPTION_PREFIX: string, the default prefix for
      instrumentation params contained within user params.
    DEFAULT_INSTRUMENTATION_ERROR_MESSAGE: string, the default error
      message to set if something has prevented something in the
      instrumentation test run from completing properly.
  """

  DEFAULT_INSTRUMENTATION_OPTION_PREFIX = 'instrumentation_option_'
  DEFAULT_INSTRUMENTATION_ERROR_MESSAGE = ('instrumentation run exited '
                                           'unexpectedly')

  def _previous_block_never_completed(self, current_block, previous_block,
                                      new_state):
    """Checks if the previous instrumentation method block completed.

    Args:
      current_block: _InstrumentationBlock, the current instrumentation
        block to check for being a different instrumentation test
        method.
      previous_block: _InstrumentationBlock, rhe previous
        instrumentation block to check for an incomplete status.
      new_state: _InstrumentationBlockStates, the next state for the
        parser, used to check for the instrumentation run ending
        with an incomplete test.

    Returns:
      A boolean indicating whether the previous instrumentation block
      completed executing.
    """
    if previous_block:
      previously_timing_block = (previous_block.status_code
                                 in _InstrumentationStatusCodeCategories.TIMING)
      currently_new_block = (current_block.status_code
                             == _InstrumentationStatusCodes.START or
                             new_state == _InstrumentationBlockStates.RESULT)
      return all([previously_timing_block, currently_new_block])
    else:
      return False

  def _create_formatters(self, instrumentation_block, new_state):
    """Creates the _InstrumentationBlockFormatters for outputting the
    instrumentation method block that have finished parsing.

    Args:
      instrumentation_block: _InstrumentationBlock, the current
        instrumentation method block to create formatters based upon.
      new_state: _InstrumentationBlockState, the next state that the
        parser will transition to.

    Returns:
      A list of the formatters tha need to create and add
      TestResultRecords to the test results.
    """
    formatters = []
    if self._previous_block_never_completed(
        current_block=instrumentation_block,
        previous_block=instrumentation_block.previous_instrumentation_block,
        new_state=new_state):
      instrumentation_block.previous_instrumentation_block.set_error_message(
          self.DEFAULT_INSTRUMENTATION_ERROR_MESSAGE)
      formatters.append(
          _InstrumentationBlockFormatter(
              instrumentation_block.previous_instrumentation_block))

    if not instrumentation_block.is_empty:
      formatters.append(_InstrumentationBlockFormatter(instrumentation_block))
    return formatters

  def _transition_instrumentation_block(
      self,
      instrumentation_block,
      new_state=_InstrumentationBlockStates.UNKNOWN):
    """Transitions and finishes the current instrumentation block.

    Args:
      instrumentation_block: _InstrumentationBlock, the current
        instrumentation block to finish.
      new_state: _InstrumentationBlockState, the next state for the
        parser to transition to.

    Returns:
      The new instrumentation block to use for storing parsed
      instrumentation output.
    """
    formatters = self._create_formatters(instrumentation_block, new_state)
    for formatter in formatters:
      test_record = formatter.create_test_record(self.TAG)
      if test_record:
        self.results.add_record(test_record)
        self.summary_writer.dump(test_record.to_dict(),
                                 records.TestSummaryEntryType.RECORD)
    return instrumentation_block.transition_state(new_state=new_state)

  def _parse_method_block_line(self, instrumentation_block, line):
    """Parses the instrumnetation method block's line.

    Args:
      instrumentation_block: _InstrumentationBlock, the current
        instrumentation method block.
      line: string, the raw instrumentation output line to parse.

    Returns:
      The next instrumentation block, which should be used to continue
      parsing instrumentation output.
    """
    if line.startswith(_InstrumentationStructurePrefixes.STATUS):
      instrumentation_block.set_key(_InstrumentationStructurePrefixes.STATUS,
                                    line)
      return instrumentation_block
    elif line.startswith(_InstrumentationStructurePrefixes.STATUS_CODE):
      instrumentation_block.set_status_code(line)
      return self._transition_instrumentation_block(instrumentation_block)
    elif line.startswith(_InstrumentationStructurePrefixes.RESULT):
      # Unexpected transition from method block -> result block
      instrumentation_block.set_key(_InstrumentationStructurePrefixes.RESULT,
                                    line)
      return self._parse_result_line(
          self._transition_instrumentation_block(
              instrumentation_block,
              new_state=_InstrumentationBlockStates.RESULT,
          ),
          line,
      )
    else:
      instrumentation_block.add_value(line)
      return instrumentation_block

  def _parse_result_block_line(self, instrumentation_block, line):
    """Parses the instrumentation result block's line.

    Args:
      instrumentation_block: _InstrumentationBlock, the instrumentation
        result block for the instrumentation run.
      line: string, the raw instrumentation output to add to the
        instrumenation result block's _InstrumentationResultBlocki
        object.

    Returns:
      The instrumentation result block for the instrumentation run.
    """
    instrumentation_block.add_value(line)
    return instrumentation_block

  def _parse_unknown_block_line(self, instrumentation_block, line):
    """Parses a line from the instrumentation output from the UNKNOWN
    parser state.

    Args:
      instrumentation_block: _InstrumentationBlock, the current
        instrumenation block, where the correct categorization it noti
        yet known.
      line: string, the raw instrumenation output line to be used to
        deteremine the correct categorization.

    Returns:
      The next instrumentation block to continue parsing with. Usually,
      this is the same instrumentation block but with the state
      transitioned appropriately.
    """
    if line.startswith(_InstrumentationStructurePrefixes.STATUS):
      return self._parse_method_block_line(
          self._transition_instrumentation_block(
              instrumentation_block,
              new_state=_InstrumentationBlockStates.METHOD,
          ),
          line,
      )
    elif (line.startswith(_InstrumentationStructurePrefixes.RESULT) or
          _InstrumentationStructurePrefixes.FAILED in line):
      return self._parse_result_block_line(
          self._transition_instrumentation_block(
              instrumentation_block,
              new_state=_InstrumentationBlockStates.RESULT,
          ),
          line,
      )
    else:
      # This would only really execute if instrumentation failed to start.
      instrumentation_block.add_value(line)
      return instrumentation_block

  def _parse_line(self, instrumentation_block, line):
    """Parses an arbitrary line from the instrumentation output based upon
    the current parser state.

    Args:
      instrumentation_block: _InstrumentationBlock, an instrumentation
        block with any of the possible parser states.
      line: string, the raw instrumentation output line to parse
        appropriately.

    Returns:
      The next instrumenation block to continue parsing with.
    """
    if instrumentation_block.state == _InstrumentationBlockStates.METHOD:
      return self._parse_method_block_line(instrumentation_block, line)
    elif instrumentation_block.state == _InstrumentationBlockStates.RESULT:
      return self._parse_result_block_line(instrumentation_block, line)
    else:
      return self._parse_unknown_block_line(instrumentation_block, line)

  def _finish_parsing(self, instrumentation_block):
    """Finishes parsing the instrumentation result block for the final
    instrumentation run status.

    Args:
      instrumentation_block: _InstrumentationBlock, the instrumentation
        result block for the instrumenation run. Potentially, thisi
        could actually be method block if the instrumentation outputi
        is malformed.

    Returns:
      A boolean indicating whether the instrumentation run completed
        with all the tests passing.

    Raises:
      signals.TestError: Error raised if the instrumentation failed to
        complete with either a pass or fail status.
    """
    formatter = _InstrumentationBlockFormatter(instrumentation_block)
    return formatter.has_completed_result_block_format(
        self.DEFAULT_INSTRUMENTATION_ERROR_MESSAGE)

  def parse_instrumentation_options(self, parameters=None):
    """Returns the options for the instrumentation test from user_params.

    By default, this method assume that the correct instrumentation options
    all start with DEFAULT_INSTRUMENTATION_OPTION_PREFIX.

    Args:
      parameters: dict, the key value pairs representing an assortment
        of parameters including instrumentation options. Usually,
        this argument will be from self.user_params.

    Returns:
      A dictionary of options/parameters for the instrumentation tst.
    """
    if parameters is None:
      return {}

    filtered_parameters = {}
    for parameter_key, parameter_value in parameters.items():
      if parameter_key.startswith(self.DEFAULT_INSTRUMENTATION_OPTION_PREFIX):
        option_key = parameter_key[len(self.
                                       DEFAULT_INSTRUMENTATION_OPTION_PREFIX):]
        filtered_parameters[option_key] = parameter_value
    return filtered_parameters

  def run_instrumentation_test(self,
                               device,
                               package,
                               options=None,
                               prefix=None,
                               runner=None):
    """Runs instrumentation tests on a device and creates test records.

    Args:
      device: AndroidDevice, the device to run instrumentation tests on.
      package: string, the package name of the instrumentation tests.
      options: dict, Instrumentation options for the instrumentation
        tests.
      prefix: string, an optional prefix for parser output for
        distinguishing between instrumentation test runs.
      runner: string, the runner to use for the instrumentation package,
        default to DEFAULT_INSTRUMENTATION_RUNNER.

    Returns:
      A boolean indicating whether or not all the instrumentation test
        methods passed.

    Raises:
      TestError if the instrumentation run crashed or if parsing the
        output failed.
    """
    # Dictionary hack to allow overwriting the instrumentation_block in the
    # parse_instrumentation closure
    instrumentation_block = [_InstrumentationBlock(prefix=prefix)]

    def parse_instrumentation(raw_line):
      line = raw_line.rstrip().decode('utf-8')
      logging.info(line)
      instrumentation_block[0] = self._parse_line(instrumentation_block[0],
                                                  line)

    device.adb.instrument(package=package,
                          options=options,
                          runner=runner,
                          handler=parse_instrumentation)

    return self._finish_parsing(instrumentation_block[0])


class BaseInstrumentationTestClass(InstrumentationTestMixin,
                                   base_test.BaseTestClass):
  """Base class for all instrumentation test classes to inherit from.

  This class extends the BaseTestClass to add functionality to run and parse
  the output of instrumentation runs.

  Attributes:
    DEFAULT_INSTRUMENTATION_OPTION_PREFIX: string, the default prefix for
      instrumentation params contained within user params.
    DEFAULT_INSTRUMENTATION_ERROR_MESSAGE: string, the default error
      message to set if something has prevented something in the
      instrumentation test run from completing properly.
  """
