from typing import List
from typing import Dict


def ExtractCases(out_lines: List[str]) -> Dict[str, List[str]]:
  """ExtractCases attempts to associate GTest names to the lines of output that
  they produce. Given a list of input like the following:

  [==========] Running 24 tests from 10 test cases.
  [----------] Global test environment set-up.
  [----------] 9 tests from ScheduleWorkTest
  [ RUN      ] ScheduleWorkTest.ThreadTimeToIOFromOneThread
  *RESULT task: 1_threads_scheduling_to_io_pump= .47606626678091973 us/task
  RESULT task_min_batch_time: 1_threads_scheduling_to_io_pump= .335 us/task
  RESULT task_max_batch_time: 1_threads_scheduling_to_io_pump= 5.071 us/task
  *RESULT task_thread_time: 1_threads_scheduling_to_io_pump= .3908787013 us/task
  [       OK ] ScheduleWorkTest.ThreadTimeToIOFromOneThread (5352 ms)
  [ RUN      ] ScheduleWorkTest.ThreadTimeToIOFromTwoThreads
  *RESULT task: 2_threads_scheduling_to_io_pump= 6.216794903666874 us/task
  RESULT task_min_batch_time: 2_threads_scheduling_to_io_pump= 2.523 us/task
  RESULT task_max_batch_time: 2_threads_scheduling_to_io_pump= 142.989 us/task
  *RESULT task_thread_time: 2_threads_scheduling_to_io_pump= 2.02621823 us/task
  [       OK ] ScheduleWorkTest.ThreadTimeToIOFromTwoThreads (5022 ms)
  [ RUN      ] ScheduleWorkTest.ThreadTimeToIOFromFourThreads

  It will first skip all lines which do not contain either RUN or RESULT.
  Then, each 'RUN' line is stripped of the bracketed portion, down to just the
  name of the test, and then placed into a dictionary that maps it to all the
  lines beneath it, up to the next RUN line. The RESULT lines all have their
  RESULT portions chopped out as well, and only the piece following RESULT is
  kept

  {'ScheduleWorkTest.ThreadTimeToIOFromOneThread':[
    'task: 1_threads_scheduling_to_io_pump= .47606626678091973 us/task',
    'task_min_batch_time: 1_threads_scheduling_to_io_pump= .335 us/task',
    'task_max_batch_time: 1_threads_scheduling_to_io_pump= 5.071 us/task',
    'task_thread_time: 1_threads_scheduling_to_io_pump= .390834314 us/task'],
  'ScheduleWorkTest.ThreadTimeToIOFromTwoThreads':[
    'task: 2_threads_scheduling_to_io_pump= 6.216794903666874 us/task',
    'task_min_batch_time: 2_threads_scheduling_to_io_pump= 2.523 us/task',
    'task_max_batch_time: 2_threads_scheduling_to_io_pump= 142.989 us/task',
    'task_thread_time: 2_threads_scheduling_to_io_pump= 2.02620013 us/task'],
  'ScheduleWorkTest.ThreadTimeToIOFromFourThreads':[]}
  """
  lines = []
  for line in out_lines:
    if "RUN" in line or "RESULT" in line:
      lines.append(line)
  cases = {}
  name = ""
  case_lines = []
  for line in lines:
    # We've hit a new test suite, write the old accumulators and start new
    # ones. The name variable is checked to make sure this isn't the first one
    # in the list of lines
    if "RUN" in line:
      if name != "":
        cases[name] = case_lines
        case_lines = []
      name = line.split("]")[-1]  # Get the actual name of the test case.

    else:
      if "RESULT" not in line:
        print("{} did not get filtered!".format(line))
      line_trimmed = line.split("RESULT")[-1].strip()
      case_lines.append(line_trimmed)
  return cases