| 
					
				 | 
			
			
				@@ -391,7 +391,7 @@ def cloud_to_prod_jobspec(language, test_case, docker_image=None, auth=False): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           cmdline=cmdline, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           cwd=cwd, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           environ=environ, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          shortname="%s:%s:%s" % (suite_name, language, test_case), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          shortname='%s:%s:%s' % (suite_name, language, test_case), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           timeout_seconds=2*60, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           flake_retries=5 if args.allow_flakes else 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           timeout_retries=2 if args.allow_flakes else 0, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -423,7 +423,7 @@ def cloud_to_cloud_jobspec(language, test_case, server_name, server_host, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           cmdline=cmdline, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           cwd=cwd, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           environ=environ, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          shortname="cloud_to_cloud:%s:%s_server:%s" % (language, server_name, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          shortname='cloud_to_cloud:%s:%s_server:%s' % (language, server_name, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                                  test_case), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           timeout_seconds=2*60, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           flake_retries=5 if args.allow_flakes else 0, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -448,7 +448,7 @@ def server_jobspec(language, docker_image): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   server_job = jobset.JobSpec( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           cmdline=docker_cmdline, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           environ=environ, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          shortname="interop_server_%s" % language, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          shortname='interop_server_%s' % language, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           timeout_seconds=30*60) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   server_job.container_name = container_name 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return server_job 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -467,16 +467,132 @@ def build_interop_image_jobspec(language, tag=None): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   # TODO(stanleycheung): find a more elegant way to do this 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if language.safename == 'php' and os.path.exists('/var/local/.composer/auth.json'): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     env['BUILD_INTEROP_DOCKER_EXTRA_ARGS'] = \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      "-v /var/local/.composer/auth.json:/root/.composer/auth.json:ro" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      '-v /var/local/.composer/auth.json:/root/.composer/auth.json:ro' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   build_job = jobset.JobSpec( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           cmdline=['tools/jenkins/build_interop_image.sh'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           environ=env, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          shortname="build_docker_%s" % (language), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          shortname='build_docker_%s' % (language), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           timeout_seconds=30*60) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   build_job.tag = tag 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return build_job 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# TODO(adelez): Use mako template. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def fill_one_test_result(shortname, resultset, html_str): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if shortname in resultset: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    result = resultset[shortname] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if result.state == 'PASSED': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      html_str = '%s<td bgcolor=\"green\">PASS</td>\n' % html_str 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      tooltip = '' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if result.returncode > 0 or result.message: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if result.returncode > 0: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          tooltip = 'returncode: %d ' % result.returncode 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if result.message: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          tooltip = '%smessage: %s' % (tooltip, result.message)      
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if result.state == 'FAILED': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        html_str = '%s<td bgcolor=\"red\">' % html_str 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if tooltip:   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          html_str = ('%s<a href=\"#\" data-toggle=\"tooltip\" ' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                      'data-placement=\"auto\" title=\"%s\">FAIL</a></td>\n' %  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                      (html_str, tooltip)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          html_str = '%sFAIL</td>\n' % html_str 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      elif result.state == 'TIMEOUT': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        html_str = '%s<td bgcolor=\"yellow\">' % html_str 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if tooltip: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          html_str = ('%s<a href=\"#\" data-toggle=\"tooltip\" ' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                      'data-placement=\"auto\" title=\"%s\">TIMEOUT</a></td>\n'  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                      % (html_str, tooltip)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          html_str = '%sTIMEOUT</td>\n' % html_str 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    html_str = '%s<td bgcolor=\"magenta\">Not implemented</td>\n' % html_str 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return html_str 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def render_html_report(test_cases, client_langs, server_langs, resultset, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                       num_failures): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  """Generate html report.""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  sorted_test_cases = sorted(test_cases) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  sorted_client_langs = sorted(client_langs) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  print sorted_client_langs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  sorted_server_langs = sorted(server_langs) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  html_str = ('<!DOCTYPE html>\n' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              '<html lang=\"en\">\n' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              '<head><title>Interop Test Result</title></head>\n' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              '<body>\n') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if num_failures > 1: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    html_str = ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '%s<p><h2><font color=\"red\">%d tests failed!</font></h2></p>\n' %  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        (html_str, num_failures)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  elif num_failures: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    html_str = ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '%s<p><h2><font color=\"red\">%d test failed!</font></h2></p>\n' %  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        (html_str, num_failures)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    html_str = ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '%s<p><h2><font color=\"green\">All tests passed!</font></h2></p>\n' %  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        html_str) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if args.cloud_to_prod_auth or args.cloud_to_prod: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # Each column header is the client language. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    html_str = ('%s<h2>Cloud to Prod</h2>\n'  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                '<table style=\"width:100%%\" border=\"1\">\n' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                '<tr bgcolor=\"#00BFFF\">\n' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                '<th/>\n') % html_str 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for client_lang in sorted_client_langs: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      html_str = '%s<th>%s\n' % (html_str, client_lang) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    html_str = '%s</tr>\n' % html_str 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for test_case in sorted_test_cases: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      html_str = '%s<tr><td><b>%s</b></td>\n' % (html_str, test_case) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      for client_lang in sorted_client_langs: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if args.cloud_to_prod: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          shortname = 'cloud_to_prod:%s:%s' % (client_lang, test_case) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          shortname = 'cloud_to_prod_auth:%s:%s' % (client_lang, test_case) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        html_str = fill_one_test_result(shortname, resultset, html_str)        
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      html_str = '%s</tr>\n' % html_str  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    html_str = '%s</table>\n' % html_str 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if servers: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for test_case in sorted_test_cases: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      # Each column header is the client language. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      html_str = ('%s<h2>%s</h2>\n'  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  '<table style=\"width:100%%\" border=\"1\">\n' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  '<tr bgcolor=\"#00BFFF\">\n' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  '<th/>\n') % (html_str, test_case) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      for client_lang in sorted_client_langs: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        html_str = '%s<th>%s\n' % (html_str, client_lang) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      html_str = '%s</tr>\n' % html_str 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      # Each row head is the server language. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      for server_lang in sorted_server_langs: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        html_str = '%s<tr><td><b>%s</b></td>\n' % (html_str, server_lang) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # Fill up the cells with test result. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for client_lang in sorted_client_langs: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          shortname = 'cloud_to_cloud:%s:%s_server:%s' % ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              client_lang, server_lang, test_case) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          html_str = fill_one_test_result(shortname, resultset, html_str) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        html_str = '%s</tr>\n' % html_str 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      html_str = '%s</table>\n' % html_str 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  html_str = ('%s\n' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              '<script>\n' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              '$(document).ready(function(){' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              '$(\'[data-toggle=\"tooltip\"]\').tooltip();\n'    
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              '});\n' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              '</script>\n' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              '</body>\n' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              '</html>') % html_str   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  # Write to reports/index.html as set up in Jenkins plugin. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  html_report_dir = 'reports' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if not os.path.exists(html_report_dir): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    os.mkdir(html_report_dir) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  html_file_path = os.path.join(html_report_dir, 'index.html') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  with open(html_file_path, 'w') as f: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    f.write(html_str) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 argp = argparse.ArgumentParser(description='Run interop tests.') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 argp.add_argument('-l', '--language', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   choices=['all'] + sorted(_LANGUAGES), 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -503,7 +619,7 @@ argp.add_argument('-s', '--server', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   default=[]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 argp.add_argument('--override_server', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   action='append', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  type=lambda kv: kv.split("="), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  type=lambda kv: kv.split('='), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   help='Use servername=HOST:PORT to explicitly specify a server. E.g. csharp=localhost:50000', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   default=[]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 argp.add_argument('-t', '--travis', 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -521,7 +637,7 @@ argp.add_argument('--allow_flakes', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   default=False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   action='store_const', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   const=True, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  help="Allow flaky tests to show as passing (re-runs failed tests up to five times)") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  help='Allow flaky tests to show as passing (re-runs failed tests up to five times)') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 args = argp.parse_args() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 servers = set(s for s in itertools.chain.from_iterable(_SERVERS 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -538,7 +654,7 @@ if args.use_docker: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     time.sleep(5) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 if not args.use_docker and servers: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  print "Running interop servers is only supported with --use_docker option enabled." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  print 'Running interop servers is only supported with --use_docker option enabled.' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   sys.exit(1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 languages = set(_LANGUAGES[l] 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -560,10 +676,14 @@ if args.use_docker: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if build_jobs: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     jobset.message('START', 'Building interop docker images.', do_newline=True) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if jobset.run(build_jobs, newline_on_success=True, maxjobs=args.jobs): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      jobset.message('SUCCESS', 'All docker images built successfully.', do_newline=True) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    num_failures, _ = jobset.run( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        build_jobs, newline_on_success=True, maxjobs=args.jobs) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if num_failures == 0: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      jobset.message('SUCCESS', 'All docker images built successfully.',  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                     do_newline=True) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      jobset.message('FAILED', 'Failed to build interop docker images.', do_newline=True) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      jobset.message('FAILED', 'Failed to build interop docker images.',  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                     do_newline=True) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       for image in docker_images.itervalues(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         dockerjob.remove_image(image, skip_nonexistent=True) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       exit(1); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -614,7 +734,7 @@ try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         jobs.append(test_job) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if not jobs: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    print "No jobs to run." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    print 'No jobs to run.' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     for image in docker_images.itervalues(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       dockerjob.remove_image(image, skip_nonexistent=True) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     sys.exit(1) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -622,13 +742,19 @@ try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   root = ET.Element('testsuites') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   testsuite = ET.SubElement(root, 'testsuite', id='1', package='grpc', name='tests') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if jobset.run(jobs, newline_on_success=True, maxjobs=args.jobs, xml_report=testsuite): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    jobset.message('SUCCESS', 'All tests passed', do_newline=True) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  num_failures, resultset = jobset.run(jobs, newline_on_success=True,  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                       maxjobs=args.jobs, xml_report=testsuite) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if num_failures: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     jobset.message('FAILED', 'Some tests failed', do_newline=True) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    jobset.message('SUCCESS', 'All tests passed', do_newline=True) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   tree = ET.ElementTree(root) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   tree.write('report.xml', encoding='UTF-8') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  # Generate HTML report. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  render_html_report(_TEST_CASES, set([str(l) for l in languages]), servers,  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                     resultset, num_failures) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 finally: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   # Check if servers are still running. 
			 |