[dev-util] Add stage_debug,symbolicate_dump endpoints to dev server

Add an endpoint to the dev server that will synchronously download
and stage the debug symbols for a given build.
Add an endpoint to the dev server that will symbolicate a minidump.

BUG=chromium-os:29850,chromium-os:30399
TEST=unit
TEST=run dev server, use curl to make it download some artifacts; ensure
TEST=debug.tgz is _not_ downloaded immediately, but that the rest of the build is staged.

TEST=run dev server, use curl to make it download debug_symbols; check to
TEST=see that debug symbols are staged in static/archive
TEST=once symbols are staged, run the dev server in your
TEST=chroot and use curl with a minidump file like this:
TEST=  curl -F minidump=@/home/cmasone/chromeos/phooey/powerd.20120424.141235.1005.dmp http://localhost:8080/symbolicate_dump

Change-Id: Ie460526396d2b9999137142c723b87793bc23aaa
Reviewed-on: https://gerrit.chromium.org/gerrit/21696
Reviewed-by: Chris Sosa <sosa@chromium.org>
Commit-Ready: Chris Masone <cmasone@chromium.org>
Tested-by: Chris Masone <cmasone@chromium.org>
diff --git a/devserver_util_unittest.py b/devserver_util_unittest.py
index 15b41ff..90f05b3 100755
--- a/devserver_util_unittest.py
+++ b/devserver_util_unittest.py
@@ -339,6 +339,78 @@
 
     self.mox.VerifyAll()
 
+  def testGatherSymbolArtifactDownloads(self):
+    """Tests that we can find debug symbol artifacts to download."""
+    build = 'R17-1413.0.0-a1-b1346'
+    archive_url_prefix = ('gs://chromeos-image-archive/x86-mario-release/' +
+                          build)
+    symbol_url = archive_url_prefix + '/' + downloadable_artifact.DEBUG_SYMBOLS
+    mock_data = 'mock data\nmock_data\nmock_data'
+    self.mox.StubOutWithMock(gsutil_util, 'GSUtilRun')
+    self.mox.StubOutWithMock(devserver_util, 'ParsePayloadList')
+
+    # GSUtil ls.
+    gsutil_util.GSUtilRun(mox.StrContains(symbol_url),
+                          mox.IgnoreArg()).AndReturn(mock_data)
+
+    self.mox.ReplayAll()
+    artifacts = devserver_util.GatherSymbolArtifactDownloads(
+        self._static_dir, archive_url_prefix, self._install_dir)
+    for index, artifact in enumerate(artifacts):
+      self.assertEqual(artifact._gs_path, symbol_url)
+      self.assertTrue(artifact._tmp_staging_dir.startswith(self._static_dir))
+
+    self.mox.VerifyAll()
+
+  def testGatherSymbolArtifactDownloadsWithRetry(self):
+    """Tests that we can poll for debug symbol artifacts to download."""
+    build = 'R17-1413.0.0-a1-b1346'
+    archive_url_prefix = ('gs://chromeos-image-archive/x86-mario-release/' +
+                          build)
+    symbol_url = archive_url_prefix + '/' + downloadable_artifact.DEBUG_SYMBOLS
+    mock_data = 'mock data\nmock_data\nmock_data'
+    self.mox.StubOutWithMock(gsutil_util, 'GSUtilRun')
+    self.mox.StubOutWithMock(devserver_util, 'ParsePayloadList')
+
+    # GSUtil ls.
+    gsutil_util.GSUtilRun(mox.StrContains(symbol_url),
+                          mox.IgnoreArg()).AndRaise(gsutil_util.GSUtilError())
+    gsutil_util.GSUtilRun(mox.StrContains(symbol_url),
+                          mox.IgnoreArg()).AndReturn(mock_data)
+
+    self.mox.ReplayAll()
+    artifacts = devserver_util.GatherSymbolArtifactDownloads(
+        self._static_dir, archive_url_prefix, self._install_dir, delay=1)
+    for index, artifact in enumerate(artifacts):
+      self.assertEqual(artifact._gs_path, symbol_url)
+      self.assertTrue(artifact._tmp_staging_dir.startswith(self._static_dir))
+
+    self.mox.VerifyAll()
+
+  def testGatherSymbolArtifactDownloadsFailAfterRetry(self):
+    """Tests that we can poll for debug symbol artifacts to download."""
+    build = 'R17-1413.0.0-a1-b1346'
+    archive_url_prefix = ('gs://chromeos-image-archive/x86-mario-release/' +
+                          build)
+    symbol_url = archive_url_prefix + '/' + downloadable_artifact.DEBUG_SYMBOLS
+    self.mox.StubOutWithMock(gsutil_util, 'GSUtilRun')
+    self.mox.StubOutWithMock(devserver_util, 'ParsePayloadList')
+
+    # GSUtil ls.
+    gsutil_util.GSUtilRun(mox.StrContains(symbol_url),
+                          mox.IgnoreArg()
+                          ).MultipleTimes().AndRaise(gsutil_util.GSUtilError())
+
+    self.mox.ReplayAll()
+    self.assertRaises(gsutil_util.GSUtilError,
+                      devserver_util.GatherSymbolArtifactDownloads,
+                      self._static_dir,
+                      archive_url_prefix,
+                      self._install_dir,
+                      timeout=1,
+                      delay=1)
+    self.mox.VerifyAll()
+
 
 if __name__ == '__main__':
   unittest.main()