EagleEye perf graphs now support autotests whose names have changed.

The JSON file specifying which performance graphs to plot has now been
restructured: the file is now a list of objects representing each test
to plot.  A test has a name, an optional list of "old_test_names" (in
case the name of the test has changed over time), and a list of graphs
to display that are associated with the test.

The scripts to extract perf values and generate perf graphs have been
adjusted to account for the changed JSON file format.  In the event that
a test is associated with one or more "old_test_names", then any perf values
from an old test name are processed and treated as if they are simply
associated with the new test name.  So a test that used to be called "X",
but is now called "Y", will show up in the graphs as test "Y", but will
implicitly include all results from both "X" and "Y" taken together.

BUG=chromium-os:38150
TEST=Verified locally that autotest desktopui_PyAutoPerf (which used to
be called desktopui_PyAutoPerfTests in the autotest database) shows up
properly in the perf graphs and contains the perf results from both
the old and new autotest names.

Change-Id: I5b41e176b5fa72f0156984b067cd14dc56f3d73b
Reviewed-on: https://gerrit.chromium.org/gerrit/43238
Reviewed-by: Richard Barnette <jrbarnette@chromium.org>
Commit-Queue: Dennis Jeffrey <dennisjeffrey@chromium.org>
Tested-by: Dennis Jeffrey <dennisjeffrey@chromium.org>
diff --git a/frontend/perf-dashboard/croschart_defaults.json b/frontend/perf-dashboard/croschart_defaults.json
index 99f421e..0c2b795 100644
--- a/frontend/perf-dashboard/croschart_defaults.json
+++ b/frontend/perf-dashboard/croschart_defaults.json
@@ -1,573 +1,596 @@
 [
   {
     "test_name": "platform_BootPerfServer",
-    "graph_name": "seconds_from_kernel",
-    "units": "sec",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "seconds_kernel_to_startup",
-      "seconds_kernel_to_startup_done",
-      "seconds_kernel_to_x_started",
-      "seconds_kernel_to_chrome_exec",
-      "seconds_kernel_to_chrome_main",
-      "seconds_kernel_to_login",
-      "seconds_kernel_to_network"
-    ]
-  },
-  {
-    "test_name": "platform_BootPerfServer",
-    "graph_name": "seconds_from_power_on",
-    "units": "sec",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "seconds_power_on_to_lf_start",
-      "seconds_power_on_to_lf_end",
-      "seconds_power_on_to_lk_start",
-      "seconds_power_on_to_lk_end",
-      "seconds_power_on_to_kernel"
-    ]
-  },
-  {
-    "test_name": "platform_BootPerfServer",
-    "graph_name": "seconds_power_on_to_login",
-    "units": "sec",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "seconds_power_on_to_login"
-    ]
-  },
-  {
-    "test_name": "platform_BootPerfServer",
-    "graph_name": "reboot_shutdown_time",
-    "units": "sec",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "seconds_reboot_time",
-      "seconds_shutdown_time"
-    ]
-  },
-  {
-    "test_name": "platform_BootPerfServer",
-    "graph_name": "rdbytes_from_kernel",
-    "units": "rdbytes",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "rdbytes_kernel_to_startup",
-      "rdbytes_kernel_to_startup_done",
-      "rdbytes_kernel_to_x_started",
-      "rdbytes_kernel_to_chrome_exec",
-      "rdbytes_kernel_to_chrome_main",
-      "rdbytes_kernel_to_login"
+    "graphs": [
+      {
+        "graph_name": "seconds_from_kernel",
+        "units": "sec",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "seconds_kernel_to_startup",
+          "seconds_kernel_to_startup_done",
+          "seconds_kernel_to_x_started",
+          "seconds_kernel_to_chrome_exec",
+          "seconds_kernel_to_chrome_main",
+          "seconds_kernel_to_login",
+          "seconds_kernel_to_network"
+        ]
+      },
+      {
+        "graph_name": "seconds_from_power_on",
+        "units": "sec",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "seconds_power_on_to_lf_start",
+          "seconds_power_on_to_lf_end",
+          "seconds_power_on_to_lk_start",
+          "seconds_power_on_to_lk_end",
+          "seconds_power_on_to_kernel"
+        ]
+      },
+      {
+        "graph_name": "seconds_power_on_to_login",
+        "units": "sec",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "seconds_power_on_to_login"
+        ]
+      },
+      {
+        "graph_name": "reboot_shutdown_time",
+        "units": "sec",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "seconds_reboot_time",
+          "seconds_shutdown_time"
+        ]
+      },
+      {
+        "graph_name": "rdbytes_from_kernel",
+        "units": "rdbytes",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "rdbytes_kernel_to_startup",
+          "rdbytes_kernel_to_startup_done",
+          "rdbytes_kernel_to_x_started",
+          "rdbytes_kernel_to_chrome_exec",
+          "rdbytes_kernel_to_chrome_main",
+          "rdbytes_kernel_to_login"
+        ]
+      }
     ]
   },
   {
     "test_name": "build_RootFilesystemSize",
-    "graph_name": "rootfs_prod",
-    "units": "bytes",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "bytes_rootfs_prod"
-    ]
-  },
-  {
-    "test_name": "build_RootFilesystemSize",
-    "graph_name": "rootfs_test",
-    "units": "bytes",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "bytes_rootfs_test"
+    "graphs": [
+      {
+        "graph_name": "rootfs_prod",
+        "units": "bytes",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "bytes_rootfs_prod"
+        ]
+      },
+      {
+        "graph_name": "rootfs_test",
+        "units": "bytes",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "bytes_rootfs_test"
+        ]
+      }
     ]
   },
   {
     "test_name": "power_LoadTest.WIFI",
-    "graph_name": "energy_rate",
-    "units": "watts",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "w_energy_rate"
-    ]
-  },
-  {
-    "test_name": "power_LoadTest.WIFI",
-    "graph_name": "battery_life",
-    "units": "min",
-    "better_direction": "higher",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "minutes_battery_life"
+    "graphs": [
+      {
+        "graph_name": "energy_rate",
+        "units": "watts",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "w_energy_rate"
+        ]
+      },
+      {
+        "graph_name": "battery_life",
+        "units": "min",
+        "better_direction": "higher",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "minutes_battery_life"
+        ]
+      }
     ]
   },
   {
     "test_name": "power_LoadTest.WIRED",
-    "graph_name": "energy_rate",
-    "units": "watts",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "w_energy_rate"
-    ]
-  },
-  {
-    "test_name": "power_LoadTest.WIRED",
-    "graph_name": "battery_life",
-    "units": "min",
-    "better_direction": "higher",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "minutes_battery_life"
+    "graphs": [
+      {
+        "graph_name": "energy_rate",
+        "units": "watts",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "w_energy_rate"
+        ]
+      },
+      {
+        "graph_name": "battery_life",
+        "units": "min",
+        "better_direction": "higher",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "minutes_battery_life"
+        ]
+      }
     ]
   },
   {
     "test_name": "power_Idle",
-    "graph_name": "enery_rate",
-    "units": "watts",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "w_energy_rate"
+    "graphs": [
+      {
+        "graph_name": "enery_rate",
+        "units": "watts",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "w_energy_rate"
+        ]
+      }
     ]
   },
   {
     "test_name": "power_Resume",
-    "graph_name": "suspend_resume_time",
-    "units": "sec",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "seconds_system_resume",
-      "seconds_system_suspend",
-      "seconds_system_resume_firmware",
-      "seconds_system_resume_kernel"
+    "graphs": [
+      {
+        "graph_name": "suspend_resume_time",
+        "units": "sec",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "seconds_system_resume",
+          "seconds_system_suspend",
+          "seconds_system_resume_firmware",
+          "seconds_system_resume_kernel"
+        ]
+      }
     ]
   },
   {
     "test_name": "hardware_MemoryThroughput",
-    "graph_name": "memory_mb_per_second",
-    "units": "mb_per_sec",
-    "better_direction": "higher",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "mb_per_sec_memory_cp_256k_seq",
-      "mb_per_sec_memory_r_256k_ran",
-      "mb_per_sec_memory_rw_256k_seq",
-      "mb_per_sec_memory_set_256k_seq",
-      "mb_per_sec_memory_w_256k_seq"
+    "graphs": [
+      {
+        "graph_name": "memory_mb_per_second",
+        "units": "mb_per_sec",
+        "better_direction": "higher",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "mb_per_sec_memory_cp_256k_seq",
+          "mb_per_sec_memory_r_256k_ran",
+          "mb_per_sec_memory_rw_256k_seq",
+          "mb_per_sec_memory_set_256k_seq",
+          "mb_per_sec_memory_w_256k_seq"
+        ]
+      }
     ]
   },
   {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "new_tab_load_time",
-    "units": "msec",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "milliseconds_NewTabPage",
-      "milliseconds_NewTabPdfPage",
-      "milliseconds_NewTabFlashPage"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "20_tabs_load_time",
-    "units": "msec",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "milliseconds_20TabsNewTabPage"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "new_tab_google_site_load_time",
-    "units": "msec",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "milliseconds_NewTabGmail",
-      "milliseconds_NewTabCalendar",
-      "milliseconds_NewTabDocs"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "upload_download_time",
-    "units": "msec",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "milliseconds_Download100MBFile",
-      "milliseconds_Upload50MBFile"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "v8_benchmark_total",
-    "units": "score",
-    "better_direction": "higher",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "score_V8Benchmark"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "v8_benchmark_breakdown",
-    "units": "score",
-    "better_direction": "higher",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "score_V8Benchmark-Richards",
-      "score_V8Benchmark-DeltaBlue",
-      "score_V8Benchmark-Crypto",
-      "score_V8Benchmark-RayTrace",
-      "score_V8Benchmark-EarleyBoyer",
-      "score_V8Benchmark-RegExp",
-      "score_V8Benchmark-Splay"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "scroll_fps",
-    "units": "fps",
-    "better_direction": "higher",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "FPS_ScrollBlankPage",
-      "FPS_ScrollTextPage",
-      "FPS_ScrollGooglePlusPage",
-      "FPS_ScrollGmail"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "flash_fps",
-    "units": "fps",
-    "better_direction": "higher",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "FPS_FlashGaming",
-      "FPS_FlashText"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "scimark_gui_mflops",
-    "units": "mflops",
-    "better_direction": "higher",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "MFLOPS_ScimarkGui-lu_factoriza",
-      "MFLOPS_ScimarkGui-fast_fourier",
-      "MFLOPS_ScimarkGui-jacobi_sor-M",
-      "MFLOPS_ScimarkGui-monte_carlo_",
-      "MFLOPS_ScimarkGui-sparse_matri"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "scimark_gui_mb",
-    "units": "mb",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "MB_ScimarkGui-lu_factorization",
-      "MB_ScimarkGui-fast_fourier_tra",
-      "MB_ScimarkGui-jacobi_sor-Mem",
-      "MB_ScimarkGui-monte_carlo_inte",
-      "MB_ScimarkGui-sparse_matrix_mu"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "sunspider_benchmark_total",
-    "units": "msec",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "ms_SunSpider-total"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "sunspider_benchmark_breakdown",
-    "units": "msec",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "ms_SunSpider-3d",
-      "ms_SunSpider-access",
-      "ms_SunSpider-bitops",
-      "ms_SunSpider-controlflow",
-      "ms_SunSpider-crypto",
-      "ms_SunSpider-date",
-      "ms_SunSpider-math",
-      "ms_SunSpider-regexp",
-      "ms_SunSpider-string"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "dromaeo_benchmark_total",
-    "units": "runs_per_sec",
-    "better_direction": "higher",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "runsPerSec_Dromaeo-total"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "dromaeo_benchmark_breakdown",
-    "units": "runs_per_sec",
-    "better_direction": "higher",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "runsPerSec_Dromaeo-RegularExpr",
-      "runsPerSec_Dromaeo-Arrays",
-      "runsPerSec_Dromaeo-Base64Encod",
-      "runsPerSec_Dromaeo-CodeEvaluat",
-      "runsPerSec_Dromaeo-Rotating3DC",
-      "runsPerSec_Dromaeo-Strings"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "youtube_dropped_frames",
-    "units": "frames",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "frames_YoutubeDroppedFramesSlo",
-      "frames_YoutubeDroppedFramesNor",
-      "frames_YoutubeDroppedFramesFas"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "youtube_cpu_usage",
-    "units": "frac_cpu_busy",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "extrapolation_YoutubeCPUExtrap"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "netflix_dropped_frames",
-    "units": "frames",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "frames_NetflixDroppedFrames"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "netflix_cpu_usage",
-    "units": "frac_cpu_busy",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "extrapolation_NetflixCPUExtrap"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "webgl_fps",
-    "units": "fps",
-    "better_direction": "higher",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "fps_WebGLAquarium",
-      "fps_WebGLField",
-      "fps_WebGLSpaceRocks"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "angry_birds_cpu_usage",
-    "units": "frac_cpu_busy",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "Fraction_AngryBirdsCpuBusy"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "angry_birds_v8_heap_size",
-    "units": "mb",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "MB_AngryBirdsV8HeapSize"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "page_cycler_group_1",
-    "units": "msec",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "milliseconds_Alexa_usFile_Page",
-      "milliseconds_MozFile_PageCycle",
-      "milliseconds_Moz2File_PageCycl"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "page_cycler_group_2",
-    "units": "msec",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "milliseconds_DhtmlFile_PageCyc",
-      "milliseconds_MoreJSFile_PageCy",
-      "milliseconds_Intl2File_PageCyc",
-      "milliseconds_Intl1File_PageCyc"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "page_cycler_bloatfile",
-    "units": "msec",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "milliseconds_BloatFile_PageCyc"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "memory_control_gemobj",
-    "units": "kb",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "KB_MemCtrl-EndGemObj-0Tabs0",
-      "KB_MemCtrl-MaxGemObj-10Tabs1",
-      "KB_MemCtrl-EndGemObj-0Tabs1",
-      "KB_MemCtrl-MaxGemObj-10Tabs2",
-      "KB_MemCtrl-EndGemObj-0Tabs2"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "memory_control_memfree",
-    "units": "kb",
-    "better_direction": "higher",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "KB_MemCtrl-EndMemFree-0Tabs0",
-      "KB_MemCtrl-MinMemFree-10Tabs1",
-      "KB_MemCtrl-EndMemFree-0Tabs1",
-      "KB_MemCtrl-MinMemFree-10Tabs2",
-      "KB_MemCtrl-EndMemFree-0Tabs2"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "memory_live_gemobj",
-    "units": "kb",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "KB_MemLive-EndGemObj-0Tabs0",
-      "KB_MemLive-MaxGemObj-10Tabs1",
-      "KB_MemLive-EndGemObj-0Tabs1",
-      "KB_MemLive-MaxGemObj-10Tabs2",
-      "KB_MemLive-EndGemObj-0Tabs2"
-    ]
-  },
-  {
-    "test_name": "desktopui_PyAutoPerfTests",
-    "graph_name": "memory_live_memfree",
-    "units": "kb",
-    "better_direction": "higher",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "KB_MemLive-EndMemFree-0Tabs0",
-      "KB_MemLive-MinMemFree-10Tabs1",
-      "KB_MemLive-EndMemFree-0Tabs1",
-      "KB_MemLive-MinMemFree-10Tabs2",
-      "KB_MemLive-EndMemFree-0Tabs2"
+    "test_name": "desktopui_PyAutoPerf",
+    "old_test_names": ["desktopui_PyAutoPerfTests"],
+    "graphs": [
+      {
+        "graph_name": "new_tab_load_time",
+        "units": "msec",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "milliseconds_NewTabPage",
+          "milliseconds_NewTabPdfPage",
+          "milliseconds_NewTabFlashPage"
+        ]
+      },
+      {
+        "graph_name": "20_tabs_load_time",
+        "units": "msec",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "milliseconds_20TabsNewTabPage"
+        ]
+      },
+      {
+        "graph_name": "new_tab_google_site_load_time",
+        "units": "msec",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "milliseconds_NewTabGmail",
+          "milliseconds_NewTabCalendar",
+          "milliseconds_NewTabDocs"
+        ]
+      },
+      {
+        "graph_name": "upload_download_time",
+        "units": "msec",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "milliseconds_Download100MBFile",
+          "milliseconds_Upload50MBFile"
+        ]
+      },
+      {
+        "graph_name": "v8_benchmark_total",
+        "units": "score",
+        "better_direction": "higher",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "score_V8Benchmark"
+        ]
+      },
+      {
+        "graph_name": "v8_benchmark_breakdown",
+        "units": "score",
+        "better_direction": "higher",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "score_V8Benchmark-Richards",
+          "score_V8Benchmark-DeltaBlue",
+          "score_V8Benchmark-Crypto",
+          "score_V8Benchmark-RayTrace",
+          "score_V8Benchmark-EarleyBoyer",
+          "score_V8Benchmark-RegExp",
+          "score_V8Benchmark-Splay"
+        ]
+      },
+      {
+        "graph_name": "scroll_fps",
+        "units": "fps",
+        "better_direction": "higher",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "FPS_ScrollBlankPage",
+          "FPS_ScrollTextPage",
+          "FPS_ScrollGooglePlusPage",
+          "FPS_ScrollGmail"
+        ]
+      },
+      {
+        "graph_name": "flash_fps",
+        "units": "fps",
+        "better_direction": "higher",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "FPS_FlashGaming",
+          "FPS_FlashText"
+        ]
+      },
+      {
+        "graph_name": "scimark_gui_mflops",
+        "units": "mflops",
+        "better_direction": "higher",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "MFLOPS_ScimarkGui-lu_factoriza",
+          "MFLOPS_ScimarkGui-fast_fourier",
+          "MFLOPS_ScimarkGui-jacobi_sor-M",
+          "MFLOPS_ScimarkGui-monte_carlo_",
+          "MFLOPS_ScimarkGui-sparse_matri"
+        ]
+      },
+      {
+        "graph_name": "scimark_gui_mb",
+        "units": "mb",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "MB_ScimarkGui-lu_factorization",
+          "MB_ScimarkGui-fast_fourier_tra",
+          "MB_ScimarkGui-jacobi_sor-Mem",
+          "MB_ScimarkGui-monte_carlo_inte",
+          "MB_ScimarkGui-sparse_matrix_mu"
+        ]
+      },
+      {
+        "graph_name": "sunspider_benchmark_total",
+        "units": "msec",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "ms_SunSpider-total"
+        ]
+      },
+      {
+        "graph_name": "sunspider_benchmark_breakdown",
+        "units": "msec",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "ms_SunSpider-3d",
+          "ms_SunSpider-access",
+          "ms_SunSpider-bitops",
+          "ms_SunSpider-controlflow",
+          "ms_SunSpider-crypto",
+          "ms_SunSpider-date",
+          "ms_SunSpider-math",
+          "ms_SunSpider-regexp",
+          "ms_SunSpider-string"
+        ]
+      },
+      {
+        "graph_name": "dromaeo_benchmark_total",
+        "units": "runs_per_sec",
+        "better_direction": "higher",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "runsPerSec_Dromaeo-total"
+        ]
+      },
+      {
+        "graph_name": "dromaeo_benchmark_breakdown",
+        "units": "runs_per_sec",
+        "better_direction": "higher",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "runsPerSec_Dromaeo-RegularExpr",
+          "runsPerSec_Dromaeo-Arrays",
+          "runsPerSec_Dromaeo-Base64Encod",
+          "runsPerSec_Dromaeo-CodeEvaluat",
+          "runsPerSec_Dromaeo-Rotating3DC",
+          "runsPerSec_Dromaeo-Strings"
+        ]
+      },
+      {
+        "graph_name": "youtube_dropped_frames",
+        "units": "frames",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "frames_YoutubeDroppedFramesSlo",
+          "frames_YoutubeDroppedFramesNor",
+          "frames_YoutubeDroppedFramesFas"
+        ]
+      },
+      {
+        "graph_name": "youtube_cpu_usage",
+        "units": "frac_cpu_busy",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "extrapolation_YoutubeCPUExtrap"
+        ]
+      },
+      {
+        "graph_name": "netflix_dropped_frames",
+        "units": "frames",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "frames_NetflixDroppedFrames"
+        ]
+      },
+      {
+        "graph_name": "netflix_cpu_usage",
+        "units": "frac_cpu_busy",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "extrapolation_NetflixCPUExtrap"
+        ]
+      },
+      {
+        "graph_name": "webgl_fps",
+        "units": "fps",
+        "better_direction": "higher",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "fps_WebGLAquarium",
+          "fps_WebGLField",
+          "fps_WebGLSpaceRocks"
+        ]
+      },
+      {
+        "graph_name": "angry_birds_cpu_usage",
+        "units": "frac_cpu_busy",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "Fraction_AngryBirdsCpuBusy"
+        ]
+      },
+      {
+        "graph_name": "angry_birds_v8_heap_size",
+        "units": "mb",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "MB_AngryBirdsV8HeapSize"
+        ]
+      },
+      {
+        "graph_name": "page_cycler_group_1",
+        "units": "msec",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "milliseconds_Alexa_usFile_Page",
+          "milliseconds_MozFile_PageCycle",
+          "milliseconds_Moz2File_PageCycl"
+        ]
+      },
+      {
+        "graph_name": "page_cycler_group_2",
+        "units": "msec",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "milliseconds_DhtmlFile_PageCyc",
+          "milliseconds_MoreJSFile_PageCy",
+          "milliseconds_Intl2File_PageCyc",
+          "milliseconds_Intl1File_PageCyc"
+        ]
+      },
+      {
+        "graph_name": "page_cycler_bloatfile",
+        "units": "msec",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "milliseconds_BloatFile_PageCyc"
+        ]
+      },
+      {
+        "graph_name": "memory_control_gemobj",
+        "units": "kb",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "KB_MemCtrl-EndGemObj-0Tabs0",
+          "KB_MemCtrl-MaxGemObj-10Tabs1",
+          "KB_MemCtrl-EndGemObj-0Tabs1",
+          "KB_MemCtrl-MaxGemObj-10Tabs2",
+          "KB_MemCtrl-EndGemObj-0Tabs2"
+        ]
+      },
+      {
+        "graph_name": "memory_control_memfree",
+        "units": "kb",
+        "better_direction": "higher",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "KB_MemCtrl-EndMemFree-0Tabs0",
+          "KB_MemCtrl-MinMemFree-10Tabs1",
+          "KB_MemCtrl-EndMemFree-0Tabs1",
+          "KB_MemCtrl-MinMemFree-10Tabs2",
+          "KB_MemCtrl-EndMemFree-0Tabs2"
+        ]
+      },
+      {
+        "graph_name": "memory_live_gemobj",
+        "units": "kb",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "KB_MemLive-EndGemObj-0Tabs0",
+          "KB_MemLive-MaxGemObj-10Tabs1",
+          "KB_MemLive-EndGemObj-0Tabs1",
+          "KB_MemLive-MaxGemObj-10Tabs2",
+          "KB_MemLive-EndGemObj-0Tabs2"
+        ]
+      },
+      {
+        "graph_name": "memory_live_memfree",
+        "units": "kb",
+        "better_direction": "higher",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "KB_MemLive-EndMemFree-0Tabs0",
+          "KB_MemLive-MinMemFree-10Tabs1",
+          "KB_MemLive-EndMemFree-0Tabs1",
+          "KB_MemLive-MinMemFree-10Tabs2",
+          "KB_MemLive-EndMemFree-0Tabs2"
+        ]
+      }
     ]
   },
   {
     "test_name": "audiovideo_FFMPEG",
-    "graph_name": "tulip_fps",
-    "units": "fps",
-    "better_direction": "higher",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "fps_tulip_hp_mp4",
-      "fps_tulip_bp_mp4",
-      "fps_tulip_ogv"
+    "graphs": [
+      {
+        "graph_name": "tulip_fps",
+        "units": "fps",
+        "better_direction": "higher",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "fps_tulip_hp_mp4",
+          "fps_tulip_bp_mp4",
+          "fps_tulip_ogv"
+        ]
+      }
     ]
   },
   {
     "test_name": "graphics_GLBench",
-    "graph_name": "glbench_benchmark",
-    "units": "units",
-    "better_direction": "???",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "1280x768_fps_compositing",
-      "mpixels_sec_clear_color",
-      "mpixels_sec_fill_solid",
-      "mpixels_sec_yuv_shader_2",
-      "mpixels_sec_yuv_shader_4",
-      "mtri_sec_triangle_setup"
+    "graphs": [
+      {
+        "graph_name": "glbench_benchmark",
+        "units": "units",
+        "better_direction": "???",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "1280x768_fps_compositing",
+          "mpixels_sec_clear_color",
+          "mpixels_sec_fill_solid",
+          "mpixels_sec_yuv_shader_2",
+          "mpixels_sec_yuv_shader_4",
+          "mtri_sec_triangle_setup"
+        ]
+      }
     ]
   },
   {
     "test_name": "graphics_GLMark2",
-    "graph_name": "glmark2_benchmark",
-    "units": "fps",
-    "better_direction": "higher",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "glmark2_score"
+    "graphs": [
+      {
+        "graph_name": "glmark2_benchmark",
+        "units": "fps",
+        "better_direction": "higher",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "glmark2_score"
+        ]
+      }
     ]
   },
   {
     "test_name": "graphics_Piglit",
-    "graph_name": "piglit_benchmark",
-    "units": "count",
-    "better_direction": "higher",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "count_subtests_pass"
+    "graphs": [
+      {
+        "graph_name": "piglit_benchmark",
+        "units": "count",
+        "better_direction": "higher",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "count_subtests_pass"
+        ]
+      }
     ]
   },
   {
     "test_name": "graphics_WebGLConformance",
-    "graph_name": "webgl_conformance",
-    "units": "count",
-    "better_direction": "higher",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "count_tests_pass"
+    "graphs": [
+      {
+        "graph_name": "webgl_conformance",
+        "units": "count",
+        "better_direction": "higher",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "count_tests_pass"
+        ]
+      }
     ]
   },
   {
     "test_name": "graphics_WebGLPerformance",
-    "graph_name": "webgl_performance",
-    "units": "msec",
-    "better_direction": "lower",
-    "info_url": "../../../../../scripts/doc/default.html",
-    "keys": [
-      "time_ms_geom_mean"
+    "graphs": [
+      {
+        "graph_name": "webgl_performance",
+        "units": "msec",
+        "better_direction": "lower",
+        "info_url": "../../../../../scripts/doc/default.html",
+        "keys": [
+          "time_ms_geom_mean"
+        ]
+      }
     ]
   }
 ]
diff --git a/frontend/perf-dashboard/extract_perf.py b/frontend/perf-dashboard/extract_perf.py
index 9cd66a1..6f69a1e 100644
--- a/frontend/perf-dashboard/extract_perf.py
+++ b/frontend/perf-dashboard/extract_perf.py
@@ -150,6 +150,9 @@
         # TODO(dennisjeffrey): Simplify the below code once the following bug
         # is addressed to standardize the platform names: crosbug.com/38521.
         match = re.search('(\w+)-r', job_name)
+        if not match:
+            unexpected_job_names.add(job_name)
+            continue
         # Only process jobs for known platforms.
         platform = match.group(1) if match.group(1) in _PLATFORMS else None
         if platform:
@@ -230,7 +233,11 @@
                   oldest_db_lookup_date)
 
     # Get unique test names.
-    test_names = set([c['test_name'] for c in charts])
+    test_names = set()
+    for c in charts:
+        test_names.add(c['test_name'])
+        if 'old_test_names' in c:
+            test_names |= set(c['old_test_names'])
 
     # Get list of already-completed job IDs so we don't re-fetch their data.
     completed_ids = set()
diff --git a/frontend/perf-dashboard/generate_perf_graphs.py b/frontend/perf-dashboard/generate_perf_graphs.py
index dacd714..69b7a61 100644
--- a/frontend/perf-dashboard/generate_perf_graphs.py
+++ b/frontend/perf-dashboard/generate_perf_graphs.py
@@ -302,11 +302,20 @@
                     f.write(simplejson.dumps(entry) + '\n')
 
 
-def process_perf_data_file(file_name, test_name, completed_ids,
-                           test_name_to_charts, options, summary_id_to_rev_num):
-    """Processes a single perf data file to convert into graphable format.
+def process_perf_data_files(file_names, test_name, completed_ids,
+                            test_name_to_charts, options,
+                            summary_id_to_rev_num):
+    """Processes data files for a single test/platform.
 
-    @param file_name: The string name of the perf data file to process.
+    Multiple data files may exist if the given test name is associated with one
+    or more old test names (i.e., the name of the test has changed over time).
+    In this case, we treat all results from the specified files as if they came
+    from a single test associated with the current test name.
+
+    This function converts the data from the specified data files into new
+    data files formatted in a way that can be graphed.
+
+    @param file_names: A list of perf data files to process.
     @param test_name: The string name of the test associated with the file name
         to process.
     @param completed_ids: A dictionary of already-processed job IDs.
@@ -320,44 +329,45 @@
     @return The number of newly-added graph data entries.
     """
     newly_added_count = 0
-    with open(file_name, 'r') as fp:
-        for line in fp.readlines():
-            info = simplejson.loads(line.strip())
-            job_id = info[0]
-            job_name = info[1]
-            platform = info[2]
-            perf_keys = info[3]
+    for file_name in file_names:
+        with open(file_name, 'r') as fp:
+            for line in fp.readlines():
+                info = simplejson.loads(line.strip())
+                job_id = info[0]
+                job_name = info[1]
+                platform = info[2]
+                perf_keys = info[3]
 
-            # Skip this job ID if it's already been processed.
-            if job_id in completed_ids:
-                continue
+                # Skip this job ID if it's already been processed.
+                if job_id in completed_ids:
+                    continue
 
-            # Scan the desired charts and see if we need to output the
-            # current line info to a graph output file.
-            for chart in test_name_to_charts[test_name]:
-                graph_name = chart['graph_name']
-                units = chart['units']
-                better_direction = chart['better_direction']
-                url = chart['info_url']
-                chart_keys = chart['keys']
+                # Scan the desired charts and see if we need to output the
+                # current line info to a graph output file.
+                for chart in test_name_to_charts[test_name]:
+                    graph_name = chart['graph_name']
+                    units = chart['units']
+                    better_direction = chart['better_direction']
+                    url = chart['info_url']
+                    chart_keys = chart['keys']
 
-                store_entry = False
-                for chart_key in chart_keys:
-                    if chart_key in [x[0] for x in perf_keys]:
-                        store_entry = True
-                        break
+                    store_entry = False
+                    for chart_key in chart_keys:
+                        if chart_key in [x[0] for x in perf_keys]:
+                            store_entry = True
+                            break
 
-                if store_entry:
-                    output_graph_data_for_entry(
-                        test_name, graph_name, job_name, platform,
-                        units, better_direction, url, perf_keys,
-                        chart_keys, options, summary_id_to_rev_num)
+                    if store_entry:
+                        output_graph_data_for_entry(
+                            test_name, graph_name, job_name, platform,
+                            units, better_direction, url, perf_keys,
+                            chart_keys, options, summary_id_to_rev_num)
 
-            # Mark this job ID as having been processed.
-            with open(_COMPLETED_ID_FILE, 'a') as fp:
-                fp.write(job_id + '\n')
-            completed_ids[job_id] = True
-            newly_added_count += 1
+                # Mark this job ID as having been processed.
+                with open(_COMPLETED_ID_FILE, 'a') as fp:
+                    fp.write(job_id + '\n')
+                completed_ids[job_id] = True
+                newly_added_count += 1
 
     return newly_added_count
 
@@ -387,11 +397,15 @@
 
     test_name_to_charts = {}
     test_names = set()
+    test_name_to_old_names = {}
+    # The _CHART_CONFIG_FILE should (and is assumed to) have one entry per
+    # test_name.  That entry should declare all graphs associated with the given
+    # test_name.
     for chart in charts:
-        if chart['test_name'] not in test_name_to_charts:
-            test_name_to_charts[chart['test_name']] = []
-        test_name_to_charts[chart['test_name']].append(chart)
+        test_name_to_charts[chart['test_name']] = chart['graphs']
         test_names.add(chart['test_name'])
+        test_name_to_old_names[chart['test_name']] = (
+            chart.get('old_test_names', []))
 
     # Scan all database data and format/output only the new data specified in
     # the graph JSON file.
@@ -407,10 +421,23 @@
         files = os.listdir(test_data_dir)
         for file_name in files:
             logging.debug('Processing perf platform data file: %s', file_name)
-            newly_added_count += process_perf_data_file(
-                os.path.join(test_data_dir, file_name), test_name,
-                completed_ids, test_name_to_charts, options,
-                summary_id_to_rev_num)
+
+            # The current test may be associated with one or more old test
+            # names for which perf results exist for the current platform.
+            # If so, we need to consider those old perf results too, as being
+            # associated with the current test/platform.
+            files_to_process = [os.path.join(test_data_dir, file_name)]
+            for old_test_name in test_name_to_old_names[test_name]:
+                old_test_file_name = os.path.join(_DATA_DIR, old_test_name,
+                                                  file_name)
+                if os.path.exists(old_test_file_name):
+                    logging.debug('(also processing this platform for old test '
+                                  'name "%s")', old_test_name)
+                    files_to_process.append(old_test_file_name)
+
+            newly_added_count += process_perf_data_files(
+                files_to_process, test_name, completed_ids,
+                test_name_to_charts, options, summary_id_to_rev_num)
 
     # Store the latest revision numbers for each test/platform/release
     # combination, to be used on the next invocation of this script.