Re: [virt-test][PATCH 6/7] virt: Adds possibility filter defaults variant from variants

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Mar 29, 2013 at 06:14:09PM +0100, Jiří Župka wrote:
> If default variant is not filtered by only or no filters then
> only default variant is chosen. This behavior was used for optimizing
> of speed of Cartesian config.
> If variants don't have default variant then everything works as usual.
> Default variant must be in variants with with_default exactly one times.
> The default variant could be filtered by only, no filter. If default
> variant is filtered from variants then variants works same as usual variants with
> default variant.
> 
> For calling Cartesian config from command line is used option -d/--defaults:
>    ../virttest/cartesian_config.py -d cfg/cc.cfg
> 
> For calling Cartesian config from python:
>    c = Parser(args[0], defaults=options.defaults, debug=options.debug)

I believe we have allow that to be per-variants-block, not
all-or-nothing.

For example: the default ./run behavior could be to automatically choose
defaults for every variants-block (guest OS, block format, etc), except
for the "subtests" variants-block.

I would like the API to look like this:

   # this would be the current behavior:
   c = Parser(..., expand_all_variants=True)
   # will expand only the "subtest" and "guest_os" variants-block, and
   # automatically choose defaults for every other variants-block:
   c = Parser(..., expand_variants=['subtest', 'guest_os'])
   # For somebody who wants to run the default tests with all Windows
   # versions:
   c = Parser(..., expand_variants=['subtest', 'windows_version'])
   # For somebody who wants to run the default tests with all CPU models,
   # and all guest OSes:
   c = Parser(..., expand_variants=['subtest', 'guest_os', 'cpu_model'])
   # (additional nice-to-have: to allow something like "guest_os.*" to
   # expand a variants-block and all its "sub-variants" (guest OS
   # version, guest OS architecture, etc)

We could also find a way to encode the "expand_variants" instruction
inside the config file syntax, so people could put that information in
their config file. But that can be done later, after we test if the
concept is really working in the Python API and command-line.

> 
> *********  example:
> variants name=tests:
>   - wait:
>        run = "wait"
>        variants:
>          - long:
>             time = short_time
>          - short: long
>             time = logn_time
>   - test2:
>        run = "test1"
> 
> variants name=virt_system, with_default:
>   - @linux:
>   - windows:
> 
> variants name=host_os, with_default:
>   - linux:
>        image = linux
>        variants with_default:
>             - ubuntu:
>             - @fedora:
>   - windows:
>        image = windows
>        variants:
>             - @XP:
>             - WIN7:
> 
> only host_os>windows
> 
> In this case is chosen from host_os variants windows variant.
> host_os>windows was choosen because default variant linux was filtered.
> Next step is select one variant from guest_os. There will be chosen only
> default variant linux because not filtered and virt_system variant is
> with with_default. There is no default variant in tests variants because
> that all of tests will be chosen.
> 
> ********  output:
> dict    1:  host_os>windows.tests>wait.long
>     dep = []
>     host_os = windows
>     image = windows
>     name = host_os>windows.XP.virt_system>linux.tests>wait.long
>     run = wait
>     shortname = host_os>windows.tests>wait.long
>     tests = wait
>     time = short_time
>     virt_system = linux
> dict    2:  host_os>windows.tests>wait.short
>     dep = ['host_os>windows.XP.virt_system>linux.tests>wait.long']
>     host_os = windows
>     image = windows
>     name = host_os>windows.XP.virt_system>linux.tests>wait.short
>     run = wait
>     shortname = host_os>windows.tests>wait.short
>     tests = wait
>     time = logn_time
>     virt_system = linux
> dict    3:  host_os>windows.tests>test2
>     dep = []
>     host_os = windows
>     image = windows
>     name = host_os>windows.XP.virt_system>linux.tests>test2
>     run = test1
>     shortname = host_os>windows.tests>test2
>     tests = test2
>     virt_system = linux
> dict    4:  host_os>windows.WIN7.tests>wait.long
>     dep = []
>     host_os = windows
>     image = windows
>     name = host_os>windows.WIN7.virt_system>linux.tests>wait.long
>     run = wait
>     shortname = host_os>windows.WIN7.tests>wait.long
>     tests = wait
>     time = short_time
>     virt_system = linux
> dict    5:  host_os>windows.WIN7.tests>wait.short
>     dep = ['host_os>windows.WIN7.virt_system>linux.tests>wait.long']
>     host_os = windows
>     image = windows
>     name = host_os>windows.WIN7.virt_system>linux.tests>wait.short
>     run = wait
>     shortname = host_os>windows.WIN7.tests>wait.short
>     tests = wait
>     time = logn_time
>     virt_system = linux
> dict    6:  host_os>windows.WIN7.tests>test2
>     dep = []
>     host_os = windows
>     image = windows
>     name = host_os>windows.WIN7.virt_system>linux.tests>test2
>     run = test1
>     shortname = host_os>windows.WIN7.tests>test2
>     tests = test2
>     virt_system = linux
> 
> Signed-off-by: Jiří Župka <jzupka@xxxxxxxxxx>
> ---
>  virttest/cartesian_config.py | 82 ++++++++++++++++++++++++++++++++++++--------
>  1 file changed, 68 insertions(+), 14 deletions(-)
> 
> diff --git a/virttest/cartesian_config.py b/virttest/cartesian_config.py
> index 04ed2b5..6cd0e88 100755
> --- a/virttest/cartesian_config.py
> +++ b/virttest/cartesian_config.py
> @@ -131,6 +131,10 @@ class ParserError:
>              return "%s (%s:%s)" % (self.msg, self.filename, self.linenum)
>  
>  
> +class MissingDefault:
> +    pass
> +
> +
>  class MissingIncludeError:
>      def __init__(self, line, filename, linenum):
>          self.line = line
> @@ -225,6 +229,7 @@ class Node(object):
>          self.labels = set()
>          self.append_to_shortname = False
>          self.failed_cases = collections.deque()
> +        self.default = False
>  
>  
>      def dump(self, indent, recurse=False):
> @@ -407,14 +412,17 @@ class Parser(object):
>  
>      @see: https://github.com/autotest/autotest/wiki/KVMAutotest-CartesianConfigParametersIntro
>      """
> -    def __init__(self, filename=None, debug=False):
> +    def __init__(self, filename=None, defaults=False, debug=False):
>          """
>          Initialize the parser and optionally parse a file.
>  
>          @param filename: Path of the file to parse.
> +        @param defaults: If True adds only defaults variant from variants
> +                         if there is some.
>          @param debug: Whether to turn on debugging output.
>          """
>          self.node = Node()
> +        self.defaults = defaults
>          self.debug = debug
>          if filename:
>              self.parse_file(filename)
> @@ -611,10 +619,18 @@ class Parser(object):
>  
>          # Recurse into children
>          count = 0
> -        for n in node.children:
> -            for d in self.get_dicts(n, ctx, new_content, shortname, dep):
> -                count += 1
> -                yield d
> +        if self.defaults:
> +            for n in node.children:
> +                for d in self.get_dicts(n, ctx, new_content, shortname, dep):
> +                    count += 1
> +                    yield d
> +                if n.default and count:
> +                    break
> +        else:
> +            for n in node.children:
> +                for d in self.get_dicts(n, ctx, new_content, shortname, dep):
> +                    count += 1
> +                    yield d
>          # Reached leaf?
>          if not node.children:
>              self._debug("    reached leaf, returning it")
> @@ -656,7 +672,8 @@ class Parser(object):
>          print s % args
>  
>  
> -    def _parse_variants(self, cr, node, prev_indent=-1, var_name=None):
> +    def _parse_variants(self, cr, node, prev_indent=-1, var_name=None,
> +                        with_default=False):
>          """
>          Read and parse lines from a FileReader object until a line with an
>          indent level lower than or equal to prev_indent is encountered.
> @@ -665,8 +682,10 @@ class Parser(object):
>          @param node: A node to operate on.
>          @param prev_indent: The indent level of the "parent" block.
>          @param var_name: Variants name
> +        @param with_default: Variants take only default variant.
>          @return: A node object.
>          """
> +        already_default = False
>          node4 = Node()
>  
>          while True:
> @@ -694,7 +713,9 @@ class Parser(object):
>              node2.labels = node.labels
>  
>              node3 = self._parse(cr, node2, prev_indent=indent)
> -            node3.name = [Label(var_name, n) for n in name.lstrip("@").split(".")]
> +            is_default = name.startswith("@")
> +            name = name.lstrip("@")
> +            node3.name = [Label(var_name, n) for n in name.split(".")]
>              node3.dep = [Label(var_name, d) for d in dep.replace(",", " ").split()]
>  
>              if var_name:
> @@ -702,12 +723,33 @@ class Parser(object):
>                  op_match = _ops_exp.search(l)
>                  node3.content += [(cr.filename, linenum, Op(l, op_match))]
>  
> -            is_default = name.startswith("@")
> -
> -            node4.children += [node3]
> +            node3.append_to_shortname = not is_default
> +
> +            if with_default and self.defaults:
> +                """
> +                Relevant only if defaults is True and
> +                variants is with default.
> +                """
> +                if is_default:
> +                    if not already_default:
> +                        node3.default = True
> +                        already_default = True
> +                    else:
> +                        raise MissingDefault
> +                if node3.default:
> +                    # Move default variant in front of rest of all variants.
> +                    # Speed optimization.
> +                    node4.children.insert(0, node3)
> +                else:
> +                    node4.children += [node3]
> +            else:
> +                node4.children += [node3]
>              node4.labels.update(node3.labels)
>              node4.labels.update(node3.name)
>  
> +        if with_default and not already_default:
> +            raise MissingDefault
> +
>          return node4
>  
>  
> @@ -751,6 +793,7 @@ class Parser(object):
>                                  char in "._-=,"):
>                              raise ParserError("Illegal characters in variants",
>                                                line, cr.filename, linenum)
> +                with_default = False
>                  var_name = None
>                  if name:
>                      block = name.split(",")
> @@ -761,12 +804,20 @@ class Parser(object):
>                                  raise ParserError("Missing name of variants",
>                                                    line, cr.filename, linenum)
>                              var_name = oper[1].strip()
> +                        elif "with_default" in oper[0]:
> +                            with_default = True
>                          else:
>                              raise ParserError("Ilegal variants param",
>                                                 line, cr.filename, linenum)
> -                node = self._parse_variants(cr, node, prev_indent=indent,
> -                                            var_name=var_name)
> -                                            var_name=name)
> +                try:
> +                    node = self._parse_variants(cr, node, prev_indent=indent,
> +                                                var_name=var_name,
> +                                                with_default=with_default)
> +                except MissingDefault:
> +                    raise ParserError("There must be exactly one default "
> +                                      "variant in variants with param "
> +                                      "with_default.",
> +                                      line, cr.filename, linenum)
>                  continue
>  
>              # Parse 'include' statements
> @@ -1040,12 +1091,15 @@ if __name__ == "__main__":
>                        help="show dict contents")
>      parser.add_option("-r", "--repr", dest="repr_mode", action="store_true",
>                        help="Output parsing results Python format")
> +    parser.add_option("-d", "--defaults", dest="defaults", action="store_true",
> +                      help="use only default variant of variants if there"
> +                           " is some")
>  
>      options, args = parser.parse_args()
>      if not args:
>          parser.error("filename required")
>  
> -    c = Parser(args[0], debug=options.debug)
> +    c = Parser(args[0], defaults=options.defaults, debug=options.debug)
>      for s in args[1:]:
>          c.parse_string(s)
>  
> -- 
> 1.8.1.4
> 

-- 
Eduardo
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux