Assorted bugs to get AU E2E test working with paygen suite.

1) Fixed a bug from a previous CL introduced that returned from an omaha
ping before we processed it for remote info (autoupdate.py)
2) If we expect a single item returned from gsutil but get multiple,
if the name we gave matches one exactly, return that.

BUG=chromium:267896
TEST=Ran it with unittests + AU E2E test with paygen test.

Change-Id: Ifd1266d9050824ad397df3bf80a1d314f01610db
Reviewed-on: https://gerrit.chromium.org/gerrit/66140
Tested-by: Chris Sosa <[email protected]>
Reviewed-by: Joy Chen <[email protected]>
Commit-Queue: Chris Sosa <[email protected]>
diff --git a/autoupdate.py b/autoupdate.py
index 52b752d..6507cdc 100644
--- a/autoupdate.py
+++ b/autoupdate.py
@@ -711,16 +711,16 @@
     # Parse the XML we got into the components we care about.
     protocol, app, event, update_check = autoupdate_lib.ParseUpdateRequest(data)
 
+    # Process attributes of the update check.
+    forced_update_label, client_version, board = self._ProcessUpdateComponents(
+        app, event)
+
     if not update_check:
       # TODO(sosa): Generate correct non-updatecheck payload to better test
       # update clients.
       _Log('Non-update check received.  Returning blank payload')
       return autoupdate_lib.GetNoUpdateResponse(protocol)
 
-    # Process attributes of the update check.
-    forced_update_label, client_version, board = self._ProcessUpdateComponents(
-        app, event)
-
     if forced_update_label:
       if label:
         _Log('Label: %s set but being overwritten to %s by request', label,
@@ -748,7 +748,7 @@
           label = self.payload_path
 
         # TODO(sosa): Remove backwards-compatible hack.
-        if not label.endswith('.bin'):
+        if not '.bin' in label:
           url = _NonePathJoin(static_urlbase, label, 'update.gz')
         else:
           url = _NonePathJoin(static_urlbase, label)
diff --git a/build_artifact.py b/build_artifact.py
index d55e6c4..432c4b2 100755
--- a/build_artifact.py
+++ b/build_artifact.py
@@ -185,6 +185,9 @@
     return '->'.join(['%s/%s' % (self.archive_url, self.name),
                      self.install_dir])
 
+  def __repr__(self):
+    return str(self)
+
 
 class AUTestPayloadBuildArtifact(BuildArtifact):
   """Wrapper for AUTest delta payloads which need additional setup."""
diff --git a/gsutil_util.py b/gsutil_util.py
index 8373047..a6e2324 100644
--- a/gsutil_util.py
+++ b/gsutil_util.py
@@ -5,6 +5,7 @@
 """Module containing gsutil helper methods."""
 
 import distutils.version
+import logging
 import random
 import re
 import subprocess
@@ -106,7 +107,9 @@
     pattern: Regular expression pattern to identify the target artifact.
     archive_url: URL of the Google Storage bucket.
     err_str: String to display in the error message on error.
-    single_item: Only a single item should be returned.
+    single_item: Only a single item should be returned. If more than one item
+                 matches the pattern errors out unless pattern matches one
+                 exactly.
     timeout/delay: optional and self-explanatory.
 
   Returns:
@@ -139,9 +142,15 @@
     found_names = _GetGSNamesFromList(uploaded_list, pattern)
     if found_names:
       if single_item and len(found_names) > 1:
-        raise PatternNotSpecific(
+        found_names_exact = _GetGSNamesFromList(uploaded_list, '^%s$' % pattern)
+        if not found_names_exact:
+          raise PatternNotSpecific(
             'Too many items %s returned by pattern %s in %s' % (
                 str(found_names), pattern, archive_url))
+        else:
+          logging.info('More than one item returned but one file matched'
+                       ' exactly so returning that: %s.', found_names_exact)
+          found_names = found_names_exact
 
       return found_names