Add an endpoint that summarizes the number of passed and failed tests per suite.

BUG=None
TEST=Manually on local setup of Autotest
DEPLOY=apache
Change-Id: I84ac81ba8b386c1317d9809d88dcc61860550386
Reviewed-on: https://chromium-review.googlesource.com/218320
Reviewed-by: Nick Matthijssen <nickam@chromium.org>
Reviewed-by: Fang Deng <fdeng@chromium.org>
Tested-by: Jesus Moises Osorio <moisesosorio@chromium.org>
Commit-Queue: Aviv Keshet <akeshet@chromium.org>
diff --git a/apache/conf/afe-directives b/apache/conf/afe-directives
index 1a7c85b..b7ef28d 100644
--- a/apache/conf/afe-directives
+++ b/apache/conf/afe-directives
@@ -11,6 +11,9 @@
 
 <Location "/afe">
     DirectoryIndex AfeClient.html
+    # Allow all requests from localhost or corp.google.com subdomains with any port
+    SetEnvIf Origin "^http(s)?://(localhost|([^/]+\.)?corp\.google\.com)(:[0-9]+)?$" origin_is=$0
+    Header set Access-Control-Allow-Origin %{origin_is}e env=origin_is
     <IfVersion >= 2.4>
         Require all granted
     </IfVersion>
diff --git a/apache/conf/new-tko-directives b/apache/conf/new-tko-directives
index f921b77..21fe7e2 100644
--- a/apache/conf/new-tko-directives
+++ b/apache/conf/new-tko-directives
@@ -11,6 +11,9 @@
 
 <Location "/new_tko">
     DirectoryIndex TkoClient.html
+    # Allow all requests from localhost or corp.google.com subdomains with any port
+    SetEnvIf Origin "^http(s)?://(localhost|([^/]+\.)?corp\.google\.com)(:[0-9]+)?$" origin_is=$0
+    Header set Access-Control-Allow-Origin %{origin_is}e env=origin_is
     <IfVersion >= 2.4>
         Require all granted
     </IfVersion>
diff --git a/frontend/afe/rpc_utils.py b/frontend/afe/rpc_utils.py
index bccc23d..687ab15 100644
--- a/frontend/afe/rpc_utils.py
+++ b/frontend/afe/rpc_utils.py
@@ -72,6 +72,18 @@
         return data
 
 
+def fetchall_as_list_of_dicts(cursor):
+    """
+    Converts each row in the cursor to a dictionary so that values can be read
+    by using the column name.
+    @param cursor: The database cursor to read from.
+    @returns: A list of each row in the cursor as a dictionary.
+    """
+    desc = cursor.description
+    return [ dict(zip([col[0] for col in desc], row))
+             for row in cursor.fetchall() ]
+
+
 def raw_http_response(response_data, content_type=None):
     response = django.http.HttpResponse(response_data, mimetype=content_type)
     response['Content-length'] = str(len(response.content))
diff --git a/frontend/tko/rpc_interface.py b/frontend/tko/rpc_interface.py
index 213eb40..e727014 100644
--- a/frontend/tko/rpc_interface.py
+++ b/frontend/tko/rpc_interface.py
@@ -1,4 +1,4 @@
-import os, pickle, datetime, itertools, operator
+import pickle, datetime, itertools, operator
 from django.db import models as dbmodels
 from autotest_lib.client.common_lib import priorities
 from autotest_lib.frontend.afe import rpc_utils, model_logic
@@ -210,6 +210,39 @@
 
     return rpc_utils.prepare_for_serialization(test_views)
 
+
+def get_tests_summary(job_names):
+    """
+    Gets the count summary of all passed and failed tests per suite.
+    @param job_names: Names of the suite jobs to get the summary from.
+    @returns: A summary of all the passed and failed tests per suite job.
+    """
+    # Take advantage of Django's literal escaping to prevent SQL injection
+    sql_list = ','.join(['%s'] * len(job_names))
+    query = ('''SELECT job_name, IF (status = 'GOOD', status, 'FAIL')
+                   AS test_status, COUNT(*) num
+                 FROM tko_test_view_2
+                 WHERE job_name IN (%s)
+                   AND test_name <> 'SERVER_JOB'
+                   AND test_name NOT LIKE 'CLIENT_JOB%%%%'
+                   AND status <> 'TEST_NA'
+                 GROUP BY job_name, IF (status = 'GOOD', status, 'FAIL')'''
+            % sql_list)
+
+    cursor = readonly_connection.connection().cursor()
+    cursor.execute(query, job_names)
+    results = rpc_utils.fetchall_as_list_of_dicts(cursor)
+
+    summaries = {}
+    for result in results:
+        label = result['job_name']
+        status = 'passed' if result['test_status'] == 'GOOD' else 'failed'
+        summary = summaries.setdefault(label, {})
+        summary[status] = result['num']
+
+    return summaries
+
+
 # graphing view support
 
 def get_hosts_and_tests():