The autotest frontend should run every test in its own step so that, if one test reboots the machine, the rest keep running.


git-svn-id: http://test.kernel.org/svn/autotest/trunk@1584 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/frontend/afe/control_file.py b/frontend/afe/control_file.py
index 8083d22..fd12926 100644
--- a/frontend/afe/control_file.py
+++ b/frontend/afe/control_file.py
@@ -4,7 +4,7 @@
 
 __author__ = 'showard@google.com (Steve Howard)'
 
-import os
+import re, os
 import frontend.settings
 
 AUTOTEST_DIR = os.path.abspath(os.path.join(
@@ -12,6 +12,7 @@
 
 
 CLIENT_KERNEL_TEMPLATE = """\
+kernel = '%(kernel)s'
 def step_init():
 	job.next_step([step_test])
 	testkernel = job.kernel('%(kernel)s')
@@ -23,6 +24,7 @@
 """
 
 SERVER_KERNEL_TEMPLATE = """\
+kernel = '%%(kernel)s'
 kernel_install_control = \"""
 %s	pass
 \"""
@@ -35,6 +37,8 @@
 
 """ % CLIENT_KERNEL_TEMPLATE
 
+CLIENT_STEP_TEMPLATE = "\tjob.next_step('step%d')\n"
+
 
 def kernel_config_line(kernel, platform):
 	if (not kernel.endswith('.rpm') and platform and
@@ -53,20 +57,43 @@
 def get_kernel_stanza(kernel, platform=None, kernel_args='', is_server=False):
 	if is_server:
 		template = SERVER_KERNEL_TEMPLATE
-		indent = ''
 	else:
 		template = CLIENT_KERNEL_TEMPLATE
-		indent = '\t'
 
 	stanza = template % {
 	    'kernel' : kernel,
 	    'kernel_config_line' : kernel_config_line(kernel, platform),
 	    'kernel_args' : kernel_args}
-	return stanza, indent
+	return stanza
 
 
-def get_tests_stanza(tests):
-	return ''.join(read_control_file(test) for test in tests)
+def add_boilerplate_to_nested_steps(lines):
+	# Look for a line that begins with 'def step_init():' while
+	# being flexible on spacing.  If it's found, this will be
+	# a nested set of steps, so add magic to make it work.
+	# See client/bin/job.py's step_engine for more info.
+	if re.search(r'^(.*\n)*def\s+step_init\s*\(\s*\)\s*:', lines):
+		lines += '\nreturn locals() '
+		lines += '# Boilerplate magic for nested sets of steps'
+	return lines
+
+
+def format_step(item, lines):
+	lines = indent_text(lines, '\t')
+	lines = 'def step%d():\n%s' % (item, lines)
+	return lines
+
+	
+def get_tests_stanza(tests, is_server, prepend=[], append=[]):
+	raw_control_files = [read_control_file(test) for test in tests]
+	if is_server:
+		return '\n'.join(raw_control_files)
+	raw_steps = prepend + [add_boilerplate_to_nested_steps(step)
+	                       for step in raw_control_files] + append
+	steps = [format_step(index, step)
+	         for index, step in enumerate(raw_steps)]
+	header = ''.join(CLIENT_STEP_TEMPLATE % i for i in xrange(len(steps)))
+	return header + '\n' + '\n\n'.join(steps)
 
 
 def indent_text(text, indent):
@@ -75,10 +102,12 @@
 
 
 def generate_control(tests, kernel=None, platform=None, is_server=False):
-	control_file = ''
-	indent = ''
+	control_file_text = ''
 	if kernel:
-		control_file, indent = get_kernel_stanza(kernel, platform,
-							 is_server=is_server)
-	control_file += indent_text(get_tests_stanza(tests), indent)
-	return control_file
+		control_file_text = get_kernel_stanza(kernel, platform,
+		                                      is_server=is_server)
+	elif not is_server:
+                control_file_text = 'def step_init():\n'
+
+	control_file_text += get_tests_stanza(tests, is_server)
+	return control_file_text