All of lore.kernel.org
 help / color / mirror / Atom feed
* [virt-test] virt: Cartesian config update v3.
@ 2013-03-29 17:14 Jiří Župka
  2013-03-29 17:14 ` [virt-test][PATCH 1/7] virt: Make Cartesian config more verbose Jiří Župka
                   ` (6 more replies)
  0 siblings, 7 replies; 18+ messages in thread
From: Jiří Župka @ 2013-03-29 17:14 UTC (permalink / raw)
  To: virt-test-devel, kvm, kvm-autotest, lmr, ldoktor, jzupka,
	ehabkost, pbonzini



Features:

virt: Adds possibility filter defaults variant from variants
virt: Adds named variants to Cartesian config.

Unittest:

virt: Update cartesian config unittest
virt: Update Cartesian config unittest named variants
virt: Update Cartesian config unittest default variants. 

Debug:

virt: Make Cartesian config more verbose
virt: Adds formal definition for Cartesian config

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [virt-test][PATCH 1/7] virt: Make Cartesian config more verbose
  2013-03-29 17:14 [virt-test] virt: Cartesian config update v3 Jiří Župka
@ 2013-03-29 17:14 ` Jiří Župka
  2013-03-29 17:14 ` [virt-test][PATCH 2/7] virt: Update cartesian config unittest Jiří Župka
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 18+ messages in thread
From: Jiří Župka @ 2013-03-29 17:14 UTC (permalink / raw)
  To: virt-test-devel, kvm, kvm-autotest, lmr, ldoktor, jzupka,
	ehabkost, pbonzini

Signed-off-by: Jiří Župka <jzupka@redhat.com>
---
 virttest/cartesian_config.py | 72 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 59 insertions(+), 13 deletions(-)

diff --git a/virttest/cartesian_config.py b/virttest/cartesian_config.py
index 318b635..092e88d 100755
--- a/virttest/cartesian_config.py
+++ b/virttest/cartesian_config.py
@@ -30,6 +30,7 @@ Cartesian configuration format file parser.
 
 import re, os, optparse, collections, string
 
+
 class ParserError:
     def __init__(self, msg, line=None, filename=None, linenum=None):
         self.msg = msg
@@ -73,25 +74,39 @@ class Node(object):
         self.failed_cases = collections.deque()
 
 
+    def dump(self, indent, recurse=False):
+        print("%s%s" % (" " * indent, self.name))
+        print("%s%s" % (" " * indent, self))
+        print("%s%s" % (" " * indent, self.content))
+        print("%s%s" % (" " * indent, self.failed_cases))
+        if recurse:
+            for child in self.children:
+                child.dump(indent + 3, recurse)
+
+
 def _match_adjacent(block, ctx, ctx_set):
-    # TODO: explain what this function does
+    """
+    It try to match as much block as possible from ctx.
+
+    @return: Count of matched blocks.
+    """
     if block[0] not in ctx_set:
         return 0
     if len(block) == 1:
-        return 1
+        return 1                          # First match and length is 1.
     if block[1] not in ctx_set:
-        return int(ctx[-1] == block[0])
+        return int(ctx[-1] == block[0])   # Check match with last from ctx.
     k = 0
     i = ctx.index(block[0])
-    while i < len(ctx):
-        if k > 0 and ctx[i] != block[k]:
+    while i < len(ctx):                   # Try to  match all of blocks.
+        if k > 0 and ctx[i] != block[k]:  # Block not match
             i -= k - 1
-            k = 0
+            k = 0                         # Start from first block in next ctx.
         if ctx[i] == block[k]:
             k += 1
-            if k >= len(block):
+            if k >= len(block):           # match all of blocks
                 break
-            if block[k] not in ctx_set:
+            if block[k] not in ctx_set:   # block in not in whole ctx.
                 break
         i += 1
     return k
@@ -99,7 +114,7 @@ def _match_adjacent(block, ctx, ctx_set):
 
 def _might_match_adjacent(block, ctx, ctx_set, descendant_labels):
     matched = _match_adjacent(block, ctx, ctx_set)
-    for elem in block[matched:]:
+    for elem in block[matched:]:        # Try to find rest of blocks in subtree
         if elem not in descendant_labels:
             return False
     return True
@@ -114,9 +129,12 @@ class Filter(object):
         for char in s:
             if not (char.isalnum() or char.isspace() or char in ".,_-"):
                 raise ParserError("Illegal characters in filter")
+        for word in s.replace(",", " ").split():                     # OR
+            word = [block.split(".") for block in word.split("..")]  # AND
         for word in s.replace(",", " ").split():
             word = [block.split(".") for block in word.split("..")]
             for block in word:
+            for block in word:                                       # .
                 for elem in block:
                     if not elem:
                         raise ParserError("Syntax error")
@@ -124,16 +142,17 @@ class Filter(object):
 
 
     def match(self, ctx, ctx_set):
-        for word in self.filter:
-            for block in word:
+        for word in self.filter:  # Go through ,
+            for block in word:    # Go through ..
                 if _match_adjacent(block, ctx, ctx_set) != len(block):
                     break
             else:
-                return True
+                return True       # All match
         return False
 
 
     def might_match(self, ctx, ctx_set, descendant_labels):
+        # There is some posibility to match in children blocks.
         for word in self.filter:
             for block in word:
                 if not _might_match_adjacent(block, ctx, ctx_set,
@@ -154,10 +173,12 @@ class NoOnlyFilter(Filter):
 
 class OnlyFilter(NoOnlyFilter):
     def is_irrelevant(self, ctx, ctx_set, descendant_labels):
+        # Matched in this tree.
         return self.match(ctx, ctx_set)
 
 
     def requires_action(self, ctx, ctx_set, descendant_labels):
+        # Impossible to match in this tree.
         return not self.might_match(ctx, ctx_set, descendant_labels)
 
 
@@ -171,6 +192,14 @@ class OnlyFilter(NoOnlyFilter):
         return False
 
 
+    def __str__(self):
+        return "Only %s" % (self.filter)
+
+
+    def __repr__(self):
+        return "Only %s" % (self.filter)
+
+
 class NoFilter(NoOnlyFilter):
     def is_irrelevant(self, ctx, ctx_set, descendant_labels):
         return not self.might_match(ctx, ctx_set, descendant_labels)
@@ -190,6 +219,14 @@ class NoFilter(NoOnlyFilter):
         return False
 
 
+    def __str__(self):
+        return "No %s" % (self.filter)
+
+
+    def __repr__(self):
+        return "No %s" % (self.filter)
+
+
 class Condition(NoFilter):
     __slots__ = ["content"]
 
@@ -380,6 +417,8 @@ class Parser(object):
                 node.failed_cases.pop()
 
         node = node or self.node
+        #if self.debug:    #Print dict on which is working now.
+        #    node.dump(0)
         # Update dep
         for d in node.dep:
             dep = dep + [".".join(ctx + [d])]
@@ -394,7 +433,10 @@ class Parser(object):
         # Check previously failed filters
         for i, failed_case in enumerate(node.failed_cases):
             if not might_pass(*failed_case):
-                self._debug("    this subtree has failed before")
+                self._debug("\n*    this subtree has failed before %s\n"
+                            "         content: %s\n"
+                            "         failcase:%s\n",
+                            name, content + node.content, failed_case)
                 del node.failed_cases[i]
                 node.failed_cases.appendleft(failed_case)
                 return
@@ -405,6 +447,7 @@ class Parser(object):
         if (not process_content(node.content, new_internal_filters) or
             not process_content(content, new_external_filters)):
             add_failed_case()
+            self._debug("Failed_cases %s", node.failed_cases)
             return
         # Update shortname
         if node.append_to_shortname:
@@ -811,5 +854,8 @@ if __name__ == "__main__":
     for s in args[1:]:
         c.parse_string(s)
 
+    if options.debug:
+        c.node.dump(0, True)
+
     dicts = c.get_dicts()
     print_dicts(options, dicts)
-- 
1.8.1.4

_______________________________________________
Virt-test-devel mailing list
Virt-test-devel@redhat.com
https://www.redhat.com/mailman/listinfo/virt-test-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [virt-test][PATCH 2/7] virt: Update cartesian config unittest
  2013-03-29 17:14 [virt-test] virt: Cartesian config update v3 Jiří Župka
  2013-03-29 17:14 ` [virt-test][PATCH 1/7] virt: Make Cartesian config more verbose Jiří Župka
@ 2013-03-29 17:14 ` Jiří Župka
  2013-03-29 17:14 ` [virt-test][PATCH 3/7] virt: Adds formal definition for Cartesian config Jiří Župka
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 18+ messages in thread
From: Jiří Župka @ 2013-03-29 17:14 UTC (permalink / raw)
  To: virt-test-devel, kvm, kvm-autotest, lmr, ldoktor, jzupka,
	ehabkost, pbonzini

Signed-off-by: Jiří Župka <jzupka@redhat.com>
---
 virttest/cartesian_config_unittest.py | 32 +++++++++++++++-----------------
 1 file changed, 15 insertions(+), 17 deletions(-)

diff --git a/virttest/cartesian_config_unittest.py b/virttest/cartesian_config_unittest.py
index c72cb71..afc1b14 100755
--- a/virttest/cartesian_config_unittest.py
+++ b/virttest/cartesian_config_unittest.py
@@ -1,4 +1,3 @@
-#!/usr/bin/python
 import unittest, logging, os
 import gzip
 import cartesian_config
@@ -38,13 +37,11 @@ class CartesianConfigTest(unittest.TestCase):
         self._checkDictionaries(p, reference)
 
 
-    def _checkStringDump(self, string, dump):
-        p = cartesian_config.Parser()
+    def _checkStringDump(self, string, dump, defaults=False):
+        p = cartesian_config.Parser(defaults=defaults)
         p.parse_string(string)
 
-        dumpdata = None
-        exec "dumpdata = " + dump
-        self._checkDictionaries(p, dumpdata)
+        self._checkDictionaries(p, dump)
 
 
     def testSimpleVariant(self):
@@ -75,17 +72,18 @@ class CartesianConfigTest(unittest.TestCase):
                         no unknown_qemu
                 - testB:
             """,
-            """[
-{'dep': [],
- 'name': 'testA.kvm.unknown_qemu',
- 'shortname': 'testA.kvm.unknown_qemu'},
-{'dep': [],
- 'name': 'testB.kvm.unknown_qemu',
- 'shortname': 'testB.kvm.unknown_qemu'},
-{'dep': [],
- 'name': 'testB.nokvm.unknown_qemu',
- 'shortname': 'testB.nokvm.unknown_qemu'},
-]""")
+            [
+                {'dep': [],
+                 'name': 'testA.kvm.unknown_qemu',
+                 'shortname': 'testA.kvm.unknown_qemu'},
+                {'dep': [],
+                 'name': 'testB.kvm.unknown_qemu',
+                 'shortname': 'testB.kvm.unknown_qemu'},
+                {'dep': [],
+                 'name': 'testB.nokvm.unknown_qemu',
+                 'shortname': 'testB.nokvm.unknown_qemu'},
+            ]
+            )
 
 
     def testHugeTest1(self):
-- 
1.8.1.4

_______________________________________________
Virt-test-devel mailing list
Virt-test-devel@redhat.com
https://www.redhat.com/mailman/listinfo/virt-test-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [virt-test][PATCH 3/7] virt: Adds formal definition for Cartesian config
  2013-03-29 17:14 [virt-test] virt: Cartesian config update v3 Jiří Župka
  2013-03-29 17:14 ` [virt-test][PATCH 1/7] virt: Make Cartesian config more verbose Jiří Župka
  2013-03-29 17:14 ` [virt-test][PATCH 2/7] virt: Update cartesian config unittest Jiří Župka
@ 2013-03-29 17:14 ` Jiří Župka
  2013-03-29 17:14 ` [virt-test][PATCH 4/7] virt: Adds named variants to " Jiří Župka
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 18+ messages in thread
From: Jiří Župka @ 2013-03-29 17:14 UTC (permalink / raw)
  To: virt-test-devel, kvm, kvm-autotest, lmr, ldoktor, jzupka,
	ehabkost, pbonzini

Signed-off-by: Jiří Župka <jzupka@redhat.com>
---
 virttest/cartesian_config.py | 85 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)

diff --git a/virttest/cartesian_config.py b/virttest/cartesian_config.py
index 092e88d..ef91051 100755
--- a/virttest/cartesian_config.py
+++ b/virttest/cartesian_config.py
@@ -25,6 +25,91 @@ Cartesian configuration format file parser.
  <filter>:
  The last one starts a conditional block.
 
+
+Formal definition:
+
+regexp from python http://docs.python.org/2/library/re.html
+Not deterministic but more readable for people.
+Spaces between terminals and nontermials are only for better
+reading of definitions.
+
+E={\n, #, :, "-", =, +=, <=, ?=, ?+=, ?<=, !, < , del, @, variants, include, only, no, name, value, exclude}
+N={S, DEL, FILTER, FILTER_NAME, FILTER_GROUP, PN_FILTER_GROUP, STAT, VARIANT, VAR-TYPE, VAR-NAME, VAR-NAME-F, VAR, COMMENT, TEXT, DEPS, DEPS-NAME-F, EXCLUDE}
+
+I = I^n | n in N              // indentation from start of line where n is indentation length.
+I = I^n+x | n,x in N          // indentation with shift
+start symbol = S
+end symbol = eps
+
+S -> I^0+x STATV | eps
+
+#
+#I^n    STATV
+#I^n    STATV
+#
+
+I^n STATV -> I^n STATV \n I^n STATV | I^n STAT | I^n variants VARIANT
+
+I^n STAT -> I^n STAT \n I^n STAT | I^n COMMENT | I^n include INC
+I^n STAT -> I^n del DEL | I^n FILTER | I^n EXCLUDE
+
+DEL -> name \n
+
+I^n STAT -> I^n name = VALUE | I^n name += VALUE | I^n name <= VALUE
+I^n STAT -> I^n name ?= VALUE | I^n name ?+= VALUE | I^n name ?<= VALUE
+
+VALUE -> TEXT \n | 'TEXT' \n | "TEXT" \n
+
+COMMENT_BLOCK -> #TEXT | //TEXT
+COMMENT ->  COMMENT_BLOCK\n
+COMMENT ->  COMMENT_BLOCK\n
+
+TEXT = [^\n] TEXT            //python format regexp
+
+#
+#I^n    variant VAR #comments:             add possibility for comment
+#I^n+x       VAR-NAME: DEPS
+#I^n+x+x2        STATV
+#I^n         VAR-NAME:
+#
+
+VARIANT -> VAR COMMENT_BLOCK\n I^n+x VAR-NAME
+VAR -> VAR-TYPE : | :                // Named | unnamed variant
+
+VAR-TYPE -> VAR-TYPE,VAR-TYPE | name=VAR-NAME-F | with_default
+
+I^n VAR-NAME -> I^n VAR-NAME \n I^n VAR-NAME | I^n VAR-NAME-N \n I^n+x STATV
+VAR-NAME-N -> - @VAR-NAME-F: DEPS | - VAR-NAME-F: DEPS
+VAR-NAME-F -> [a-zA-Z0-9\._-]+                  // Python regexp
+
+DEPS -> DEPS-NAME-F | DEPS-NAME-F,DEPS
+DEPS-NAME-F -> [a-zA-Z0-9\._- ]+                  // Python regexp
+
+INC -> name \n
+
+#
+# FILTER_GROUP: STAT
+#     STAT
+#
+I^n STAT -> I^n PN_FILTER_GROUP | I^n ! PN_FILTER_GROUP
+
+PN_FILTER_GROUP -> FILTER_GROUP: \n I^n+x STAT | FILTER_GROUP: STAT \n I^n+x STAT
+
+#
+# only FILTER_GROUP
+# no FILTER_GROUP
+
+FILTER -> only FILTER_GROUP \n | no FILTER_GROUP \n
+
+FILTER_GROUP -> FILTER_NAME
+FILTER_GROUP -> FILTER_GROUP..FILTER_GROUP
+FILTER_GROUP -> FILTER_GROUP,FILTER_GROUP
+
+FILTER_NAME -> FILTER_NAME.FILTER_NAME
+FILTER_NAME -> VAR-NAME-F | VAR-NAME-F=VAR-NAME-F
+
+EXCLUDE -> exclude FILTER
+
 @copyright: Red Hat 2008-2011
 """
 
-- 
1.8.1.4

_______________________________________________
Virt-test-devel mailing list
Virt-test-devel@redhat.com
https://www.redhat.com/mailman/listinfo/virt-test-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [virt-test][PATCH 4/7] virt: Adds named variants to Cartesian config.
  2013-03-29 17:14 [virt-test] virt: Cartesian config update v3 Jiří Župka
                   ` (2 preceding siblings ...)
  2013-03-29 17:14 ` [virt-test][PATCH 3/7] virt: Adds formal definition for Cartesian config Jiří Župka
@ 2013-03-29 17:14 ` Jiří Župka
  2013-04-01 14:30   ` Eduardo Habkost
  2013-04-16  6:50   ` Alex Jia
  2013-03-29 17:14 ` [virt-test][PATCH 5/7] virt: Update Cartesian config unittest named variants Jiří Župka
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 18+ messages in thread
From: Jiří Župka @ 2013-03-29 17:14 UTC (permalink / raw)
  To: virt-test-devel, kvm, kvm-autotest, lmr, ldoktor, jzupka,
	ehabkost, pbonzini

******** example:
variants name=tests:
  - wait:
       run = "wait"
       variants:
         - long:
            time = short_time
         - short: long
            time = logn_time
  - test2:
       run = "test1"

variants name=virt_system:
  - linux:
  - windows_XP:

variants name=host_os:
  - linux:
       image = linux
  - windows_XP:
       image = windows

tests>wait.short:
    shutdown = destroy

only host_os>linux

******** output:
dict    1:  host_os>linux.virt_system>linux.tests>wait.long
    dep = []
    host_os = linux
    image = linux
    name = host_os>linux.virt_system>linux.tests>wait.long
    run = wait
    shortname = host_os>linux.virt_system>linux.tests>wait.long
    tests = wait
    time = short_time
    virt_system = linux
dict    2:  host_os>linux.virt_system>linux.tests>wait.short
    dep = ['host_os>linux.virt_system>linux.tests>wait.long']
    host_os = linux
    image = linux
    name = host_os>linux.virt_system>linux.tests>wait.short
    run = wait
    shortname = host_os>linux.virt_system>linux.tests>wait.short
    shutdown = destroy
    tests = wait
    time = logn_time
    virt_system = linux
dict    3:  host_os>linux.virt_system>linux.tests>test2
    dep = []
    host_os = linux
    image = linux
    name = host_os>linux.virt_system>linux.tests>test2
    run = test1
    shortname = host_os>linux.virt_system>linux.tests>test2
    tests = test2
    virt_system = linux
dict    4:  host_os>linux.virt_system>windows_XP.tests>wait.long
    dep = []
    host_os = linux
    image = linux
    name = host_os>linux.virt_system>windows_XP.tests>wait.long
    run = wait
    shortname = host_os>linux.virt_system>windows_XP.tests>wait.long
    tests = wait
    time = short_time
    virt_system = windows_XP
dict    5:  host_os>linux.virt_system>windows_XP.tests>wait.short
    dep = ['host_os>linux.virt_system>windows_XP.tests>wait.long']
    host_os = linux
    image = linux
    name = host_os>linux.virt_system>windows_XP.tests>wait.short
    run = wait
    shortname = host_os>linux.virt_system>windows_XP.tests>wait.short
    shutdown = destroy
    tests = wait
    time = logn_time
    virt_system = windows_XP
dict    6:  host_os>linux.virt_system>windows_XP.tests>test2
    dep = []
    host_os = linux
    image = linux
    name = host_os>linux.virt_system>windows_XP.tests>test2
    run = test1
    shortname = host_os>linux.virt_system>windows_XP.tests>test2
    tests = test2
    virt_system = windows_XP

For filtering of named variants is used character ">" because there was
problem with conflict with = in expression key = value. The char ">"
could be changed to something better but it should be different from "="
for optimization of speed.

Additionally named variant adds keys to final dictionary in case of
example is it (virt_system = linux). It should reduce size of config file.
Keys defined in config and keys defined by named variants are in same
name space.

Signed-off-by: Jiří Župka <jzupka@redhat.com>
---
 virttest/cartesian_config.py | 138 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 124 insertions(+), 14 deletions(-)

diff --git a/virttest/cartesian_config.py b/virttest/cartesian_config.py
index ef91051..04ed2b5 100755
--- a/virttest/cartesian_config.py
+++ b/virttest/cartesian_config.py
@@ -145,6 +145,74 @@ class MissingIncludeError:
 num_failed_cases = 5
 
 
+class Label(object):
+    __slots__ = ["name", "var_name", "long_name", "hash_val", "hash_var"]
+
+    def __init__(self, name, next_name=None):
+        if next_name is None:
+            self.name = name
+            self.var_name = None
+        else:
+            self.name = next_name
+            self.var_name = name
+
+        if self.var_name is None:
+            self.long_name = "%s" % (self.name)
+        else:
+            self.long_name = "%s>%s" % (self.var_name, self.name)
+
+        self.hash_val = self.hash_name()
+        self.hash_var = None
+        if self.var_name:
+            self.hash_var = self.hash_variant()
+
+
+    def __str__(self):
+        return self.long_name
+
+
+    def __repr__(self):
+        return self.long_name
+
+
+    def __eq__(self, o):
+        """
+        The comparison is asymmetric due to optimization.
+        """
+        if o.var_name:
+            if self.long_name == o.long_name:
+                return True
+        else:
+            if self.name == o.name:
+                    return True
+        return False
+
+
+    def __ne__(self, o):
+        """
+        The comparison is asymmetric due to optimization.
+        """
+        if o.var_name:
+            if self.long_name != o.long_name:
+                return True
+        else:
+            if self.name != o.name:
+                    return True
+        return False
+
+
+    def __hash__(self):
+        return self.hash_val
+
+
+    def hash_name(self):
+        return sum([i + 1 * ord(x) for i, x in enumerate(self.name)])
+
+
+    def hash_variant(self):
+        return sum([i + 1 * ord(x) for i, x in enumerate(str(self))])
+
+
 class Node(object):
     __slots__ = ["name", "dep", "content", "children", "labels",
                  "append_to_shortname", "failed_cases", "default"]
@@ -212,18 +280,19 @@ class Filter(object):
     def __init__(self, s):
         self.filter = []
         for char in s:
-            if not (char.isalnum() or char.isspace() or char in ".,_-"):
+            if not (char.isalnum() or char.isspace() or char in ".,_->"):
                 raise ParserError("Illegal characters in filter")
         for word in s.replace(",", " ").split():                     # OR
             word = [block.split(".") for block in word.split("..")]  # AND
-        for word in s.replace(",", " ").split():
-            word = [block.split(".") for block in word.split("..")]
-            for block in word:
+            words = []
             for block in word:                                       # .
+                b = []
                 for elem in block:
                     if not elem:
                         raise ParserError("Syntax error")
-            self.filter += [word]
+                    b.append(Label(*elem.split(">")))
+                words.append(b)
+            self.filter += [words]
 
 
     def match(self, ctx, ctx_set):
@@ -506,15 +575,16 @@ class Parser(object):
         #    node.dump(0)
         # Update dep
         for d in node.dep:
-            dep = dep + [".".join(ctx + [d])]
+            dep = dep + [".".join([str(label) for label in ctx + [d]])]
         # Update ctx
         ctx = ctx + node.name
         ctx_set = set(ctx)
         labels = node.labels
         # Get the current name
-        name = ".".join(ctx)
+        name = ".".join([str(label) for label in ctx])
         if node.name:
             self._debug("checking out %r", name)
+
         # Check previously failed filters
         for i, failed_case in enumerate(node.failed_cases):
             if not might_pass(*failed_case):
@@ -534,9 +604,11 @@ class Parser(object):
             add_failed_case()
             self._debug("Failed_cases %s", node.failed_cases)
             return
+
         # Update shortname
         if node.append_to_shortname:
             shortname = shortname + node.name
+
         # Recurse into children
         count = 0
         for n in node.children:
@@ -546,7 +618,8 @@ class Parser(object):
         # Reached leaf?
         if not node.children:
             self._debug("    reached leaf, returning it")
-            d = {"name": name, "dep": dep, "shortname": ".".join(shortname)}
+            d = {"name": name, "dep": dep,
+                 "shortname": ".".join([str(sn) for sn in shortname])}
             for _, _, op in new_content:
                 op.apply_to_dict(d)
             yield d
@@ -583,7 +656,7 @@ class Parser(object):
         print s % args
 
 
-    def _parse_variants(self, cr, node, prev_indent=-1):
+    def _parse_variants(self, cr, node, prev_indent=-1, var_name=None):
         """
         Read and parse lines from a FileReader object until a line with an
         indent level lower than or equal to prev_indent is encountered.
@@ -591,6 +664,7 @@ class Parser(object):
         @param cr: A FileReader/StrReader object.
         @param node: A node to operate on.
         @param prev_indent: The indent level of the "parent" block.
+        @param var_name: Variants name
         @return: A node object.
         """
         node4 = Node()
@@ -620,9 +694,15 @@ class Parser(object):
             node2.labels = node.labels
 
             node3 = self._parse(cr, node2, prev_indent=indent)
-            node3.name = name.lstrip("@").split(".")
-            node3.dep = dep.replace(",", " ").split()
-            node3.append_to_shortname = not name.startswith("@")
+            node3.name = [Label(var_name, n) for n in name.lstrip("@").split(".")]
+            node3.dep = [Label(var_name, d) for d in dep.replace(",", " ").split()]
+
+            if var_name:
+                l = "%s = %s" % (var_name, name)
+                op_match = _ops_exp.search(l)
+                node3.content += [(cr.filename, linenum, Op(l, op_match))]
+
+            is_default = name.startswith("@")
 
             node4.children += [node3]
             node4.labels.update(node3.labels)
@@ -649,14 +729,44 @@ class Parser(object):
             words = line.split(None, 1)
 
             # Parse 'variants'
-            if line == "variants:":
+            if line.startswith("variants"):
                 # 'variants' is not allowed inside a conditional block
                 if (isinstance(node, Condition) or
                     isinstance(node, NegativeCondition)):
                     raise ParserError("'variants' is not allowed inside a "
                                       "conditional block",
                                       None, cr.filename, linenum)
-                node = self._parse_variants(cr, node, prev_indent=indent)
+                name = None
+                if not words[0] in ["variants", "variants:"]:
+                    raise ParserError("Illegal characters in variants",
+                                       line, cr.filename, linenum)
+                if words[0] == "variants":
+                    try:
+                        name, _ = words[1].split(":")  # split name and comment
+                    except ValueError:
+                        raise ParserError("Missing : in variants expression",
+                                              line, cr.filename, linenum)
+                    for char in name:
+                        if not (char.isalnum() or char.isspace() or
+                                char in "._-=,"):
+                            raise ParserError("Illegal characters in variants",
+                                              line, cr.filename, linenum)
+                var_name = None
+                if name:
+                    block = name.split(",")
+                    for b in block:
+                        oper = b.split("=")
+                        if oper[0] == "name":
+                            if len(oper) == 1:
+                                raise ParserError("Missing name of variants",
+                                                  line, cr.filename, linenum)
+                            var_name = oper[1].strip()
+                        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)
                 continue
 
             # Parse 'include' statements
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [virt-test][PATCH 5/7] virt: Update Cartesian config unittest named variants
  2013-03-29 17:14 [virt-test] virt: Cartesian config update v3 Jiří Župka
                   ` (3 preceding siblings ...)
  2013-03-29 17:14 ` [virt-test][PATCH 4/7] virt: Adds named variants to " Jiří Župka
@ 2013-03-29 17:14 ` Jiří Župka
  2013-04-01 14:21   ` Eduardo Habkost
  2013-03-29 17:14 ` [virt-test][PATCH 6/7] virt: Adds possibility filter defaults variant from variants Jiří Župka
  2013-03-29 17:14 ` [virt-test][PATCH 7/7] virt: Update Cartesian config unittest default variants Jiří Župka
  6 siblings, 1 reply; 18+ messages in thread
From: Jiří Župka @ 2013-03-29 17:14 UTC (permalink / raw)
  To: virt-test-devel, kvm, kvm-autotest, lmr, ldoktor, jzupka,
	ehabkost, pbonzini

Signed-off-by: Jiří Župka <jzupka@redhat.com>
---
 virttest/cartesian_config_unittest.py | 79 +++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/virttest/cartesian_config_unittest.py b/virttest/cartesian_config_unittest.py
index afc1b14..98c1efc 100755
--- a/virttest/cartesian_config_unittest.py
+++ b/virttest/cartesian_config_unittest.py
@@ -86,6 +86,85 @@ class CartesianConfigTest(unittest.TestCase):
             )
 
 
+    def testNameVariant(self):
+        self._checkStringDump("""
+            variants name=tests: # All tests in configuration
+              - wait:
+                   run = "wait"
+                   variants:
+                     - long:
+                        time = short_time
+                     - short: long
+                        time = logn_time
+              - test2:
+                   run = "test1"
+            
+            variants name=virt_system:
+              - @linux:
+              - windows:
+            
+            variants name=host_os:
+              - linux:
+                   image = linux
+              - windows:
+                   image = windows
+            
+            only host_os>linux
+            """,
+            [
+                {'dep': [],
+                 'host_os': 'linux',
+                 'image': 'linux',
+                 'name': 'host_os>linux.virt_system>linux.tests>wait.long',
+                 'run': 'wait',
+                 'shortname': 'host_os>linux.tests>wait.long',
+                 'tests': 'wait',
+                 'time': 'short_time',
+                 'virt_system': 'linux'},
+                {'dep': ['host_os>linux.virt_system>linux.tests>wait.long'],
+                 'host_os': 'linux',
+                 'image': 'linux',
+                 'name': 'host_os>linux.virt_system>linux.tests>wait.short',
+                 'run': 'wait',
+                 'shortname': 'host_os>linux.tests>wait.short',
+                 'tests': 'wait',
+                 'time': 'logn_time',
+                 'virt_system': 'linux'},
+                {'dep': [],
+                 'host_os': 'linux',
+                 'image': 'linux',
+                 'name': 'host_os>linux.virt_system>linux.tests>test2',
+                 'run': 'test1',
+                 'shortname': 'host_os>linux.tests>test2',
+                 'tests': 'test2',
+                 'virt_system': 'linux'},
+                {'dep': [],
+                 'host_os': 'linux',
+                 'image': 'linux',
+                 'name': 'host_os>linux.virt_system>windows.tests>wait.long',
+                 'run': 'wait',
+                 'shortname': 'host_os>linux.virt_system>windows.tests>wait.long',
+                 'tests': 'wait',
+                 'time': 'short_time',
+                 'virt_system': 'windows'},
+                {'dep': ['host_os>linux.virt_system>windows.tests>wait.long'],
+                 'host_os': 'linux',
+                 'image': 'linux',
+                 'name': 'host_os>linux.virt_system>windows.tests>wait.short',
+                 'run': 'wait',
+                 'shortname': 'host_os>linux.virt_system>windows.tests>wait.short',
+                 'tests': 'wait',
+                 'time': 'logn_time',
+                 'virt_system': 'windows'},
+                {'dep': [],
+                 'host_os': 'linux',
+                 'image': 'linux',
+                 'name': 'host_os>linux.virt_system>windows.tests>test2',
+                 'run': 'test1',
+                 'shortname': 'host_os>linux.virt_system>windows.tests>test2',
+                 'tests': 'test2',
+                 'virt_system': 'windows'},
+            ])
     def testHugeTest1(self):
         self._checkConfigDump('testcfg.huge/test1.cfg',
                               'testcfg.huge/test1.cfg.repr.gz')
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [virt-test][PATCH 6/7] virt: Adds possibility filter defaults variant from variants
  2013-03-29 17:14 [virt-test] virt: Cartesian config update v3 Jiří Župka
                   ` (4 preceding siblings ...)
  2013-03-29 17:14 ` [virt-test][PATCH 5/7] virt: Update Cartesian config unittest named variants Jiří Župka
@ 2013-03-29 17:14 ` Jiří Župka
  2013-04-01 14:40   ` Eduardo Habkost
  2013-03-29 17:14 ` [virt-test][PATCH 7/7] virt: Update Cartesian config unittest default variants Jiří Župka
  6 siblings, 1 reply; 18+ messages in thread
From: Jiří Župka @ 2013-03-29 17:14 UTC (permalink / raw)
  To: virt-test-devel, kvm, kvm-autotest, lmr, ldoktor, jzupka,
	ehabkost, pbonzini

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)

*********  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@redhat.com>
---
 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

_______________________________________________
Virt-test-devel mailing list
Virt-test-devel@redhat.com
https://www.redhat.com/mailman/listinfo/virt-test-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [virt-test][PATCH 7/7] virt: Update Cartesian config unittest default variants.
  2013-03-29 17:14 [virt-test] virt: Cartesian config update v3 Jiří Župka
                   ` (5 preceding siblings ...)
  2013-03-29 17:14 ` [virt-test][PATCH 6/7] virt: Adds possibility filter defaults variant from variants Jiří Župka
@ 2013-03-29 17:14 ` Jiří Župka
  6 siblings, 0 replies; 18+ messages in thread
From: Jiří Župka @ 2013-03-29 17:14 UTC (permalink / raw)
  To: virt-test-devel, kvm, kvm-autotest, lmr, ldoktor, jzupka,
	ehabkost, pbonzini

Signed-off-by: Jiří Župka <jzupka@redhat.com>
---
 virttest/cartesian_config_unittest.py | 96 +++++++++++++++++++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/virttest/cartesian_config_unittest.py b/virttest/cartesian_config_unittest.py
index 98c1efc..4f5e50c 100755
--- a/virttest/cartesian_config_unittest.py
+++ b/virttest/cartesian_config_unittest.py
@@ -165,6 +165,102 @@ class CartesianConfigTest(unittest.TestCase):
                  'tests': 'test2',
                  'virt_system': 'windows'},
             ])
+
+
+    def testDefaults(self):
+        self._checkStringDump("""
+            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
+              - @windows:
+                   image = windows
+            """,
+            [
+                {'dep': [],
+                 'host_os': 'windows',
+                 'image': 'windows',
+                 'name': 'host_os>windows.virt_system>linux.tests>wait.long',
+                 'run': 'wait',
+                 'shortname': 'tests>wait.long',
+                 'tests': 'wait',
+                 'time': 'short_time',
+                 'virt_system': 'linux'},
+                {'dep': ['host_os>windows.virt_system>linux.tests>wait.long'],
+                 'host_os': 'windows',
+                 'image': 'windows',
+                 'name': 'host_os>windows.virt_system>linux.tests>wait.short',
+                 'run': 'wait',
+                 'shortname': 'tests>wait.short',
+                 'tests': 'wait',
+                 'time': 'logn_time',
+                 'virt_system': 'linux'},
+                {'dep': [],
+                 'host_os': 'windows',
+                 'image': 'windows',
+                 'name': 'host_os>windows.virt_system>linux.tests>test2',
+                 'run': 'test1',
+                 'shortname': 'tests>test2',
+                 'tests': 'test2',
+                 'virt_system': 'linux'},
+                ]
+            , True)
+
+
+    def testDefaultsExactlyOne(self):
+        with self.assertRaises(cartesian_config.ParserError):
+            self._checkStringDump("""
+                variants name=host_os, with_default:
+                  - @linux:
+                       image = linux
+                       variants with_default:
+                            - ubuntu:
+                            - @fedora:
+                  - @windows:
+                       image = windows
+                       variants:
+                            - @XP:
+                            - WIN7:
+                
+                only host_os>windows
+                """,
+                []
+                , True)
+
+        with self.assertRaises(cartesian_config.ParserError):
+            self._checkStringDump("""
+                variants name=host_os, with_default:
+                  - linux:
+                       image = linux
+                       variants with_default:
+                            - ubuntu:
+                            - @fedora:
+                  - windows:
+                       image = windows
+                       variants:
+                            - @XP:
+                            - WIN7:
+                
+                only host_os>windows
+                """,
+                []
+                , True)
+
+
     def testHugeTest1(self):
         self._checkConfigDump('testcfg.huge/test1.cfg',
                               'testcfg.huge/test1.cfg.repr.gz')
-- 
1.8.1.4

_______________________________________________
Virt-test-devel mailing list
Virt-test-devel@redhat.com
https://www.redhat.com/mailman/listinfo/virt-test-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [virt-test][PATCH 5/7] virt: Update Cartesian config unittest named variants
  2013-03-29 17:14 ` [virt-test][PATCH 5/7] virt: Update Cartesian config unittest named variants Jiří Župka
@ 2013-04-01 14:21   ` Eduardo Habkost
  0 siblings, 0 replies; 18+ messages in thread
From: Eduardo Habkost @ 2013-04-01 14:21 UTC (permalink / raw)
  To: Jiří Župka; +Cc: kvm, virt-test-devel, pbonzini, kvm-autotest

I will start by reviewing the test code, so we can agree on expected
syntax/behavior, before reviewing the implementation:

On Fri, Mar 29, 2013 at 06:14:08PM +0100, Jiří Župka wrote:
> Signed-off-by: Jiří Župka <jzupka@redhat.com>
> ---
>  virttest/cartesian_config_unittest.py | 79 +++++++++++++++++++++++++++++++++++
>  1 file changed, 79 insertions(+)

What about squashing this into the previous patch? I don't see a reason
to put unit-tests and implementation in separate commits.

> 
> diff --git a/virttest/cartesian_config_unittest.py b/virttest/cartesian_config_unittest.py
> index afc1b14..98c1efc 100755
> --- a/virttest/cartesian_config_unittest.py
> +++ b/virttest/cartesian_config_unittest.py
> @@ -86,6 +86,85 @@ class CartesianConfigTest(unittest.TestCase):
>              )
>  
>  
> +    def testNameVariant(self):
> +        self._checkStringDump("""
> +            variants name=tests: # All tests in configuration

I like how you tried to make the syntax extensible, but:

1) I dislike the fact that all variants-block "metadata" will have to be
stuck in a single line if we extend this.

2) I find the model required to understand what "name=tests" means
confusing. With the syntax above, "name" (the left-hand side of the "="
sign) is a kind of variable/option name, but the right-hand side of the
"=" sign ("tests") is _also_ a variable/option name.

I mean: on all programming languages I know, variables are declared like
this:

  var i;
or:
  int i;

not like this:

  var name=i;
or:
  var type=int name=i;

That said, I would love to have extensibility to allow other
variants-block metadata in the future, but I think the variants-block
_name_ is special and doesn't need to be prepended with "name=". IMO,
the "name=" prefix makes the semantics more confusing, not clearer.

> +              - wait:
> +                   run = "wait"
> +                   variants:
> +                     - long:
> +                        time = short_time
> +                     - short: long
> +                        time = logn_time
> +              - test2:
> +                   run = "test1"
> +            
> +            variants name=virt_system:
> +              - @linux:
> +              - windows:
> +            
> +            variants name=host_os:
> +              - linux:
> +                   image = linux
> +              - windows:
> +                   image = windows
> +            
> +            only host_os>linux

That this ">" syntax mean? Is it something new?

Is the ">" operator whitespace-sensitive? Would "host_os > linux" work?

> +            """,
> +            [
> +                {'dep': [],
> +                 'host_os': 'linux',
> +                 'image': 'linux',
> +                 'name': 'host_os>linux.virt_system>linux.tests>wait.long',
> +                 'run': 'wait',
> +                 'shortname': 'host_os>linux.tests>wait.long',
> +                 'tests': 'wait',
> +                 'time': 'short_time',
> +                 'virt_system': 'linux'},
> +                {'dep': ['host_os>linux.virt_system>linux.tests>wait.long'],
> +                 'host_os': 'linux',
> +                 'image': 'linux',
> +                 'name': 'host_os>linux.virt_system>linux.tests>wait.short',
> +                 'run': 'wait',
> +                 'shortname': 'host_os>linux.tests>wait.short',
> +                 'tests': 'wait',
> +                 'time': 'logn_time',
> +                 'virt_system': 'linux'},
> +                {'dep': [],
> +                 'host_os': 'linux',
> +                 'image': 'linux',
> +                 'name': 'host_os>linux.virt_system>linux.tests>test2',
> +                 'run': 'test1',
> +                 'shortname': 'host_os>linux.tests>test2',
> +                 'tests': 'test2',
> +                 'virt_system': 'linux'},
> +                {'dep': [],
> +                 'host_os': 'linux',
> +                 'image': 'linux',
> +                 'name': 'host_os>linux.virt_system>windows.tests>wait.long',
> +                 'run': 'wait',
> +                 'shortname': 'host_os>linux.virt_system>windows.tests>wait.long',
> +                 'tests': 'wait',
> +                 'time': 'short_time',
> +                 'virt_system': 'windows'},
> +                {'dep': ['host_os>linux.virt_system>windows.tests>wait.long'],
> +                 'host_os': 'linux',
> +                 'image': 'linux',
> +                 'name': 'host_os>linux.virt_system>windows.tests>wait.short',
> +                 'run': 'wait',
> +                 'shortname': 'host_os>linux.virt_system>windows.tests>wait.short',
> +                 'tests': 'wait',
> +                 'time': 'logn_time',
> +                 'virt_system': 'windows'},
> +                {'dep': [],
> +                 'host_os': 'linux',
> +                 'image': 'linux',
> +                 'name': 'host_os>linux.virt_system>windows.tests>test2',
> +                 'run': 'test1',
> +                 'shortname': 'host_os>linux.virt_system>windows.tests>test2',
> +                 'tests': 'test2',
> +                 'virt_system': 'windows'},
> +            ])
>      def testHugeTest1(self):
>          self._checkConfigDump('testcfg.huge/test1.cfg',
>                                'testcfg.huge/test1.cfg.repr.gz')
> -- 
> 1.8.1.4
> 

-- 
Eduardo

_______________________________________________
Virt-test-devel mailing list
Virt-test-devel@redhat.com
https://www.redhat.com/mailman/listinfo/virt-test-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [virt-test][PATCH 4/7] virt: Adds named variants to Cartesian config.
  2013-03-29 17:14 ` [virt-test][PATCH 4/7] virt: Adds named variants to " Jiří Župka
@ 2013-04-01 14:30   ` Eduardo Habkost
  2013-04-04 16:14     ` Jiri Zupka
  2013-04-16  6:50   ` Alex Jia
  1 sibling, 1 reply; 18+ messages in thread
From: Eduardo Habkost @ 2013-04-01 14:30 UTC (permalink / raw)
  To: Jiří Župka; +Cc: kvm, virt-test-devel, pbonzini, kvm-autotest

Sorry for not reading the commit message before my previous reply. Now I
see the origin of the ">" syntax.

On Fri, Mar 29, 2013 at 06:14:07PM +0100, Jiří Župka wrote:
[...]
> 
> For filtering of named variants is used character ">" because there was
> problem with conflict with = in expression key = value. The char ">"
> could be changed to something better but it should be different from "="
> for optimization of speed.

IMO we need really strong reasons to use anything different from "="
because it is the most obvious choice we have. Using ">" doesn't make
any sense to me.

What kind of speed optimization are you talking about, exactly? We need
to keep algorithm time/space complexity under control, but making two or
three additional regexp matches per line won't make the code much
slower, will it?

Also: whatever symbol we use, I would really like to make it
whitespace-insensitive.

I mean: if "foo>x" or "foo=x" works, "foo > x" or "foo = x" should work,
too. I am absolutely sure people _will_ eventually try to put whitespace
around the operator symbol, and this shouldn't cause unpleasant
surprises.


> 
> Additionally named variant adds keys to final dictionary in case of
> example is it (virt_system = linux). It should reduce size of config file.
> Keys defined in config and keys defined by named variants are in same
> name space.

This is the part I like the most. Thanks!


> 
> Signed-off-by: Jiří Župka <jzupka@redhat.com>
> ---
>  virttest/cartesian_config.py | 138 ++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 124 insertions(+), 14 deletions(-)
> 
> diff --git a/virttest/cartesian_config.py b/virttest/cartesian_config.py
> index ef91051..04ed2b5 100755
> --- a/virttest/cartesian_config.py
> +++ b/virttest/cartesian_config.py
> @@ -145,6 +145,74 @@ class MissingIncludeError:
>  num_failed_cases = 5
>  
>  
> +class Label(object):
> +    __slots__ = ["name", "var_name", "long_name", "hash_val", "hash_var"]
> +
> +    def __init__(self, name, next_name=None):
> +        if next_name is None:
> +            self.name = name
> +            self.var_name = None
> +        else:
> +            self.name = next_name
> +            self.var_name = name
> +
> +        if self.var_name is None:
> +            self.long_name = "%s" % (self.name)
> +        else:
> +            self.long_name = "%s>%s" % (self.var_name, self.name)
> +
> +        self.hash_val = self.hash_name()
> +        self.hash_var = None
> +        if self.var_name:
> +            self.hash_var = self.hash_variant()
> +
> +
> +    def __str__(self):
> +        return self.long_name
> +
> +
> +    def __repr__(self):
> +        return self.long_name
> +
> +
> +    def __eq__(self, o):
> +        """
> +        The comparison is asymmetric due to optimization.
> +        """
> +        if o.var_name:
> +            if self.long_name == o.long_name:
> +                return True
> +        else:
> +            if self.name == o.name:
> +                    return True
> +        return False
> +
> +
> +    def __ne__(self, o):
> +        """
> +        The comparison is asymmetric due to optimization.
> +        """
> +        if o.var_name:
> +            if self.long_name != o.long_name:
> +                return True
> +        else:
> +            if self.name != o.name:
> +                    return True
> +        return False
> +
> +
> +    def __hash__(self):
> +        return self.hash_val
> +
> +
> +    def hash_name(self):
> +        return sum([i + 1 * ord(x) for i, x in enumerate(self.name)])
> +
> +
> +    def hash_variant(self):
> +        return sum([i + 1 * ord(x) for i, x in enumerate(str(self))])
> +
> +
>  class Node(object):
>      __slots__ = ["name", "dep", "content", "children", "labels",
>                   "append_to_shortname", "failed_cases", "default"]
> @@ -212,18 +280,19 @@ class Filter(object):
>      def __init__(self, s):
>          self.filter = []
>          for char in s:
> -            if not (char.isalnum() or char.isspace() or char in ".,_-"):
> +            if not (char.isalnum() or char.isspace() or char in ".,_->"):
>                  raise ParserError("Illegal characters in filter")
>          for word in s.replace(",", " ").split():                     # OR
>              word = [block.split(".") for block in word.split("..")]  # AND
> -        for word in s.replace(",", " ").split():
> -            word = [block.split(".") for block in word.split("..")]
> -            for block in word:
> +            words = []
>              for block in word:                                       # .
> +                b = []
>                  for elem in block:
>                      if not elem:
>                          raise ParserError("Syntax error")
> -            self.filter += [word]
> +                    b.append(Label(*elem.split(">")))
> +                words.append(b)
> +            self.filter += [words]
>  
>  
>      def match(self, ctx, ctx_set):
> @@ -506,15 +575,16 @@ class Parser(object):
>          #    node.dump(0)
>          # Update dep
>          for d in node.dep:
> -            dep = dep + [".".join(ctx + [d])]
> +            dep = dep + [".".join([str(label) for label in ctx + [d]])]
>          # Update ctx
>          ctx = ctx + node.name
>          ctx_set = set(ctx)
>          labels = node.labels
>          # Get the current name
> -        name = ".".join(ctx)
> +        name = ".".join([str(label) for label in ctx])
>          if node.name:
>              self._debug("checking out %r", name)
> +
>          # Check previously failed filters
>          for i, failed_case in enumerate(node.failed_cases):
>              if not might_pass(*failed_case):
> @@ -534,9 +604,11 @@ class Parser(object):
>              add_failed_case()
>              self._debug("Failed_cases %s", node.failed_cases)
>              return
> +
>          # Update shortname
>          if node.append_to_shortname:
>              shortname = shortname + node.name
> +
>          # Recurse into children
>          count = 0
>          for n in node.children:
> @@ -546,7 +618,8 @@ class Parser(object):
>          # Reached leaf?
>          if not node.children:
>              self._debug("    reached leaf, returning it")
> -            d = {"name": name, "dep": dep, "shortname": ".".join(shortname)}
> +            d = {"name": name, "dep": dep,
> +                 "shortname": ".".join([str(sn) for sn in shortname])}
>              for _, _, op in new_content:
>                  op.apply_to_dict(d)
>              yield d
> @@ -583,7 +656,7 @@ class Parser(object):
>          print s % args
>  
>  
> -    def _parse_variants(self, cr, node, prev_indent=-1):
> +    def _parse_variants(self, cr, node, prev_indent=-1, var_name=None):
>          """
>          Read and parse lines from a FileReader object until a line with an
>          indent level lower than or equal to prev_indent is encountered.
> @@ -591,6 +664,7 @@ class Parser(object):
>          @param cr: A FileReader/StrReader object.
>          @param node: A node to operate on.
>          @param prev_indent: The indent level of the "parent" block.
> +        @param var_name: Variants name
>          @return: A node object.
>          """
>          node4 = Node()
> @@ -620,9 +694,15 @@ class Parser(object):
>              node2.labels = node.labels
>  
>              node3 = self._parse(cr, node2, prev_indent=indent)
> -            node3.name = name.lstrip("@").split(".")
> -            node3.dep = dep.replace(",", " ").split()
> -            node3.append_to_shortname = not name.startswith("@")
> +            node3.name = [Label(var_name, n) for n in name.lstrip("@").split(".")]
> +            node3.dep = [Label(var_name, d) for d in dep.replace(",", " ").split()]
> +
> +            if var_name:
> +                l = "%s = %s" % (var_name, name)
> +                op_match = _ops_exp.search(l)
> +                node3.content += [(cr.filename, linenum, Op(l, op_match))]
> +
> +            is_default = name.startswith("@")
>  
>              node4.children += [node3]
>              node4.labels.update(node3.labels)
> @@ -649,14 +729,44 @@ class Parser(object):
>              words = line.split(None, 1)
>  
>              # Parse 'variants'
> -            if line == "variants:":
> +            if line.startswith("variants"):
>                  # 'variants' is not allowed inside a conditional block
>                  if (isinstance(node, Condition) or
>                      isinstance(node, NegativeCondition)):
>                      raise ParserError("'variants' is not allowed inside a "
>                                        "conditional block",
>                                        None, cr.filename, linenum)
> -                node = self._parse_variants(cr, node, prev_indent=indent)
> +                name = None
> +                if not words[0] in ["variants", "variants:"]:
> +                    raise ParserError("Illegal characters in variants",
> +                                       line, cr.filename, linenum)
> +                if words[0] == "variants":
> +                    try:
> +                        name, _ = words[1].split(":")  # split name and comment
> +                    except ValueError:
> +                        raise ParserError("Missing : in variants expression",
> +                                              line, cr.filename, linenum)
> +                    for char in name:
> +                        if not (char.isalnum() or char.isspace() or
> +                                char in "._-=,"):
> +                            raise ParserError("Illegal characters in variants",
> +                                              line, cr.filename, linenum)
> +                var_name = None
> +                if name:
> +                    block = name.split(",")
> +                    for b in block:
> +                        oper = b.split("=")
> +                        if oper[0] == "name":
> +                            if len(oper) == 1:
> +                                raise ParserError("Missing name of variants",
> +                                                  line, cr.filename, linenum)
> +                            var_name = oper[1].strip()
> +                        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)
>                  continue
>  
>              # Parse 'include' statements
> -- 
> 1.8.1.4
> 

-- 
Eduardo

_______________________________________________
Virt-test-devel mailing list
Virt-test-devel@redhat.com
https://www.redhat.com/mailman/listinfo/virt-test-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [virt-test][PATCH 6/7] virt: Adds possibility filter defaults variant from variants
  2013-03-29 17:14 ` [virt-test][PATCH 6/7] virt: Adds possibility filter defaults variant from variants Jiří Župka
@ 2013-04-01 14:40   ` Eduardo Habkost
  0 siblings, 0 replies; 18+ messages in thread
From: Eduardo Habkost @ 2013-04-01 14:40 UTC (permalink / raw)
  To: Jiří Župka; +Cc: kvm, virt-test-devel, pbonzini, kvm-autotest

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@redhat.com>
> ---
>  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

_______________________________________________
Virt-test-devel mailing list
Virt-test-devel@redhat.com
https://www.redhat.com/mailman/listinfo/virt-test-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [virt-test][PATCH 4/7] virt: Adds named variants to Cartesian config.
  2013-04-01 14:30   ` Eduardo Habkost
@ 2013-04-04 16:14     ` Jiri Zupka
  0 siblings, 0 replies; 18+ messages in thread
From: Jiri Zupka @ 2013-04-04 16:14 UTC (permalink / raw)
  To: Eduardo Habkost; +Cc: kvm, virt-test-devel, pbonzini, kvm-autotest



----- Original Message -----
> Sorry for not reading the commit message before my previous reply. Now I
> see the origin of the ">" syntax.
> 
> On Fri, Mar 29, 2013 at 06:14:07PM +0100, Jiří Župka wrote:
> [...]
> > 
> > For filtering of named variants is used character ">" because there was
> > problem with conflict with = in expression key = value. The char ">"
> > could be changed to something better but it should be different from "="
> > for optimization of speed.
> 
> IMO we need really strong reasons to use anything different from "="
> because it is the most obvious choice we have. Using ">" doesn't make
> any sense to me.


There is not necessary solve conflict with = or : in code. Code parsing is
straightforward with that . Chars "=" and ":" was one of my first selection
too but it brings conflicts in parsing. But it could be changed because
there were more voice against it. Users could prefer better syntax instead
of little improve of speed.


> 
> What kind of speed optimization are you talking about, exactly? We need
> to keep algorithm time/space complexity under control, but making two or
> three additional regexp matches per line won't make the code much
> slower, will it?


Sometime yes (https://github.com/autotest/virt-test/pull/229).
But I don't think that it is this case. I'll will try think about more.


> Also: whatever symbol we use, I would really like to make it
> whitespace-insensitive.
> 
> I mean: if "foo>x" or "foo=x" works, "foo > x" or "foo = x" should work,
> too. I am absolutely sure people _will_ eventually try to put whitespace
> around the operator symbol, and this shouldn't cause unpleasant
> surprises.

Thank a lot that you catch this bug. It is only bug not intention.
I have forgot one strip(). But I will repair the bug after we will
finish discussion about named variant.

> 
> 
> > 
> > Additionally named variant adds keys to final dictionary in case of
> > example is it (virt_system = linux). It should reduce size of config file.
> > Keys defined in config and keys defined by named variants are in same
> > name space.
> 
> This is the part I like the most. Thanks!
> 
> 
> > 
> > Signed-off-by: Jiří Župka <jzupka@redhat.com>
> > ---
> >  virttest/cartesian_config.py | 138
> >  ++++++++++++++++++++++++++++++++++++++-----
> >  1 file changed, 124 insertions(+), 14 deletions(-)
> > 
> > diff --git a/virttest/cartesian_config.py b/virttest/cartesian_config.py
> > index ef91051..04ed2b5 100755
> > --- a/virttest/cartesian_config.py
> > +++ b/virttest/cartesian_config.py
> > @@ -145,6 +145,74 @@ class MissingIncludeError:
> >  num_failed_cases = 5
> >  
> >  
> > +class Label(object):
> > +    __slots__ = ["name", "var_name", "long_name", "hash_val", "hash_var"]
> > +
> > +    def __init__(self, name, next_name=None):
> > +        if next_name is None:
> > +            self.name = name
> > +            self.var_name = None
> > +        else:
> > +            self.name = next_name
> > +            self.var_name = name
> > +
> > +        if self.var_name is None:
> > +            self.long_name = "%s" % (self.name)
> > +        else:
> > +            self.long_name = "%s>%s" % (self.var_name, self.name)
> > +
> > +        self.hash_val = self.hash_name()
> > +        self.hash_var = None
> > +        if self.var_name:
> > +            self.hash_var = self.hash_variant()
> > +
> > +
> > +    def __str__(self):
> > +        return self.long_name
> > +
> > +
> > +    def __repr__(self):
> > +        return self.long_name
> > +
> > +
> > +    def __eq__(self, o):
> > +        """
> > +        The comparison is asymmetric due to optimization.
> > +        """
> > +        if o.var_name:
> > +            if self.long_name == o.long_name:
> > +                return True
> > +        else:
> > +            if self.name == o.name:
> > +                    return True
> > +        return False
> > +
> > +
> > +    def __ne__(self, o):
> > +        """
> > +        The comparison is asymmetric due to optimization.
> > +        """
> > +        if o.var_name:
> > +            if self.long_name != o.long_name:
> > +                return True
> > +        else:
> > +            if self.name != o.name:
> > +                    return True
> > +        return False
> > +
> > +
> > +    def __hash__(self):
> > +        return self.hash_val
> > +
> > +
> > +    def hash_name(self):
> > +        return sum([i + 1 * ord(x) for i, x in enumerate(self.name)])
> > +
> > +
> > +    def hash_variant(self):
> > +        return sum([i + 1 * ord(x) for i, x in enumerate(str(self))])
> > +
> > +
> >  class Node(object):
> >      __slots__ = ["name", "dep", "content", "children", "labels",
> >                   "append_to_shortname", "failed_cases", "default"]
> > @@ -212,18 +280,19 @@ class Filter(object):
> >      def __init__(self, s):
> >          self.filter = []
> >          for char in s:
> > -            if not (char.isalnum() or char.isspace() or char in ".,_-"):
> > +            if not (char.isalnum() or char.isspace() or char in ".,_->"):
> >                  raise ParserError("Illegal characters in filter")
> >          for word in s.replace(",", " ").split():                     # OR
> >              word = [block.split(".") for block in word.split("..")]  # AND
> > -        for word in s.replace(",", " ").split():
> > -            word = [block.split(".") for block in word.split("..")]
> > -            for block in word:
> > +            words = []
> >              for block in word:                                       # .
> > +                b = []
> >                  for elem in block:
> >                      if not elem:
> >                          raise ParserError("Syntax error")
> > -            self.filter += [word]
> > +                    b.append(Label(*elem.split(">")))
> > +                words.append(b)
> > +            self.filter += [words]
> >  
> >  
> >      def match(self, ctx, ctx_set):
> > @@ -506,15 +575,16 @@ class Parser(object):
> >          #    node.dump(0)
> >          # Update dep
> >          for d in node.dep:
> > -            dep = dep + [".".join(ctx + [d])]
> > +            dep = dep + [".".join([str(label) for label in ctx + [d]])]
> >          # Update ctx
> >          ctx = ctx + node.name
> >          ctx_set = set(ctx)
> >          labels = node.labels
> >          # Get the current name
> > -        name = ".".join(ctx)
> > +        name = ".".join([str(label) for label in ctx])
> >          if node.name:
> >              self._debug("checking out %r", name)
> > +
> >          # Check previously failed filters
> >          for i, failed_case in enumerate(node.failed_cases):
> >              if not might_pass(*failed_case):
> > @@ -534,9 +604,11 @@ class Parser(object):
> >              add_failed_case()
> >              self._debug("Failed_cases %s", node.failed_cases)
> >              return
> > +
> >          # Update shortname
> >          if node.append_to_shortname:
> >              shortname = shortname + node.name
> > +
> >          # Recurse into children
> >          count = 0
> >          for n in node.children:
> > @@ -546,7 +618,8 @@ class Parser(object):
> >          # Reached leaf?
> >          if not node.children:
> >              self._debug("    reached leaf, returning it")
> > -            d = {"name": name, "dep": dep, "shortname":
> > ".".join(shortname)}
> > +            d = {"name": name, "dep": dep,
> > +                 "shortname": ".".join([str(sn) for sn in shortname])}
> >              for _, _, op in new_content:
> >                  op.apply_to_dict(d)
> >              yield d
> > @@ -583,7 +656,7 @@ class Parser(object):
> >          print s % args
> >  
> >  
> > -    def _parse_variants(self, cr, node, prev_indent=-1):
> > +    def _parse_variants(self, cr, node, prev_indent=-1, var_name=None):
> >          """
> >          Read and parse lines from a FileReader object until a line with an
> >          indent level lower than or equal to prev_indent is encountered.
> > @@ -591,6 +664,7 @@ class Parser(object):
> >          @param cr: A FileReader/StrReader object.
> >          @param node: A node to operate on.
> >          @param prev_indent: The indent level of the "parent" block.
> > +        @param var_name: Variants name
> >          @return: A node object.
> >          """
> >          node4 = Node()
> > @@ -620,9 +694,15 @@ class Parser(object):
> >              node2.labels = node.labels
> >  
> >              node3 = self._parse(cr, node2, prev_indent=indent)
> > -            node3.name = name.lstrip("@").split(".")
> > -            node3.dep = dep.replace(",", " ").split()
> > -            node3.append_to_shortname = not name.startswith("@")
> > +            node3.name = [Label(var_name, n) for n in
> > name.lstrip("@").split(".")]
> > +            node3.dep = [Label(var_name, d) for d in dep.replace(",", "
> > ").split()]
> > +
> > +            if var_name:
> > +                l = "%s = %s" % (var_name, name)
> > +                op_match = _ops_exp.search(l)
> > +                node3.content += [(cr.filename, linenum, Op(l, op_match))]
> > +
> > +            is_default = name.startswith("@")
> >  
> >              node4.children += [node3]
> >              node4.labels.update(node3.labels)
> > @@ -649,14 +729,44 @@ class Parser(object):
> >              words = line.split(None, 1)
> >  
> >              # Parse 'variants'
> > -            if line == "variants:":
> > +            if line.startswith("variants"):
> >                  # 'variants' is not allowed inside a conditional block
> >                  if (isinstance(node, Condition) or
> >                      isinstance(node, NegativeCondition)):
> >                      raise ParserError("'variants' is not allowed inside a
> >                      "
> >                                        "conditional block",
> >                                        None, cr.filename, linenum)
> > -                node = self._parse_variants(cr, node, prev_indent=indent)
> > +                name = None
> > +                if not words[0] in ["variants", "variants:"]:
> > +                    raise ParserError("Illegal characters in variants",
> > +                                       line, cr.filename, linenum)
> > +                if words[0] == "variants":
> > +                    try:
> > +                        name, _ = words[1].split(":")  # split name and
> > comment
> > +                    except ValueError:
> > +                        raise ParserError("Missing : in variants
> > expression",
> > +                                              line, cr.filename, linenum)
> > +                    for char in name:
> > +                        if not (char.isalnum() or char.isspace() or
> > +                                char in "._-=,"):
> > +                            raise ParserError("Illegal characters in
> > variants",
> > +                                              line, cr.filename, linenum)
> > +                var_name = None
> > +                if name:
> > +                    block = name.split(",")
> > +                    for b in block:
> > +                        oper = b.split("=")
> > +                        if oper[0] == "name":
> > +                            if len(oper) == 1:
> > +                                raise ParserError("Missing name of
> > variants",
> > +                                                  line, cr.filename,
> > linenum)
> > +                            var_name = oper[1].strip()
> > +                        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)
> >                  continue
> >  
> >              # Parse 'include' statements
> > --
> > 1.8.1.4
> > 
> 
> --
> Eduardo
> 

_______________________________________________
Virt-test-devel mailing list
Virt-test-devel@redhat.com
https://www.redhat.com/mailman/listinfo/virt-test-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [virt-test][PATCH 4/7] virt: Adds named variants to Cartesian config.
  2013-03-29 17:14 ` [virt-test][PATCH 4/7] virt: Adds named variants to " Jiří Župka
  2013-04-01 14:30   ` Eduardo Habkost
@ 2013-04-16  6:50   ` Alex Jia
  2013-04-16 12:03     ` Jiri Zupka
  1 sibling, 1 reply; 18+ messages in thread
From: Alex Jia @ 2013-04-16  6:50 UTC (permalink / raw)
  To: Jiří Župka; +Cc: kvm, virt-test-devel, pbonzini, kvm-autotest

On 03/30/2013 01:14 AM, Jiří Župka wrote:
> variants name=tests:
>    - wait:
>         run = "wait"
>         variants:
>           - long:
>              time = short_time
>           - short: long
>              time = logn_time
>    - test2:
>         run = "test1"
>
> variants name=virt_system:
>    - linux:
>    - windows_XP:
>
> variants name=host_os:
>    - linux:
>         image = linux
>    - windows_XP:
>         image = windows
>
> tests>wait.short:
>      shutdown = destroy
>
> only host_os>linux
Jiří , I pasted above above example into demo.cfg and ran it via 
cartesian parser then I got the error "__main__.ParserError: 'variants' 
is not allowed inside a conditional block 
(libvirt/tests/cfg/demo.cfg:4)", any wrong with me? thanks.

_______________________________________________
Virt-test-devel mailing list
Virt-test-devel@redhat.com
https://www.redhat.com/mailman/listinfo/virt-test-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [virt-test][PATCH 4/7] virt: Adds named variants to Cartesian config.
  2013-04-16  6:50   ` Alex Jia
@ 2013-04-16 12:03     ` Jiri Zupka
  2013-04-16 14:16       ` Jiri Zupka
  0 siblings, 1 reply; 18+ messages in thread
From: Jiri Zupka @ 2013-04-16 12:03 UTC (permalink / raw)
  To: Alex Jia; +Cc: kvm, virt-test-devel, pbonzini, kvm-autotest

Hi Alex,
  I hope you use "new" version of cart config in github https://github.com/autotest/virt-test/pull/255.
This was older RFC version of vart config. And I'm preparing new version based on communication with Eduardo and Pablo.

If you don't please loot at documentation https://github.com/autotest/virt-test/wiki/VirtTestDocumentation#wiki-id26 
This documentation says how it works now.

regards
  Jiří Župka

----- Original Message -----
> On 03/30/2013 01:14 AM, Jiří Župka wrote:
> > variants name=tests:
> >    - wait:
> >         run = "wait"
> >         variants:
> >           - long:
> >              time = short_time
> >           - short: long
> >              time = logn_time
> >    - test2:
> >         run = "test1"
> >
> > variants name=virt_system:
> >    - linux:
> >    - windows_XP:
> >
> > variants name=host_os:
> >    - linux:
> >         image = linux
> >    - windows_XP:
> >         image = windows
> >
> > tests>wait.short:
> >      shutdown = destroy
> >
> > only host_os>linux
> Jiří , I pasted above above example into demo.cfg and ran it via
> cartesian parser then I got the error "__main__.ParserError: 'variants'
> is not allowed inside a conditional block
> (libvirt/tests/cfg/demo.cfg:4)", any wrong with me? thanks.
> 
> 

_______________________________________________
Virt-test-devel mailing list
Virt-test-devel@redhat.com
https://www.redhat.com/mailman/listinfo/virt-test-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [virt-test][PATCH 4/7] virt: Adds named variants to Cartesian config.
  2013-04-16 12:03     ` Jiri Zupka
@ 2013-04-16 14:16       ` Jiri Zupka
  2013-04-17  2:47         ` Alex Jia
  0 siblings, 1 reply; 18+ messages in thread
From: Jiri Zupka @ 2013-04-16 14:16 UTC (permalink / raw)
  To: Alex Jia; +Cc: kvm, virt-test-devel, pbonzini, kvm-autotest

Hi Alex,
  thanks again for review. I recognize now what you mean. I thought that
you another thread of mails. I was try it again with
https://github.com/autotest/virt-test/pull/255 and demo example works.

If you are interest in this feature. Check new version which I'll send in
future days. There will be some changes in syntax and will be added lexer
for better filtering.

regards,
  Jiří Župka



----- Original Message -----
> Hi Alex,
>   I hope you use "new" version of cart config in github
>   https://github.com/autotest/virt-test/pull/255.
> This was older RFC version of vart config. And I'm preparing new version
> based on communication with Eduardo and Pablo.
> 
> If you don't please loot at documentation
> https://github.com/autotest/virt-test/wiki/VirtTestDocumentation#wiki-id26
> This documentation says how it works now.
> 
> regards
>   Jiří Župka
> 
> ----- Original Message -----
> > On 03/30/2013 01:14 AM, Jiří Župka wrote:
> > > variants name=tests:
> > >    - wait:
> > >         run = "wait"
> > >         variants:
> > >           - long:
> > >              time = short_time
> > >           - short: long
> > >              time = logn_time
> > >    - test2:
> > >         run = "test1"
> > >
> > > variants name=virt_system:
> > >    - linux:
> > >    - windows_XP:
> > >
> > > variants name=host_os:
> > >    - linux:
> > >         image = linux
> > >    - windows_XP:
> > >         image = windows
> > >
> > > tests>wait.short:
> > >      shutdown = destroy
> > >
> > > only host_os>linux
> > Jiří , I pasted above above example into demo.cfg and ran it via
> > cartesian parser then I got the error "__main__.ParserError: 'variants'
> > is not allowed inside a conditional block
> > (libvirt/tests/cfg/demo.cfg:4)", any wrong with me? thanks.
> > 
> > 
> 

_______________________________________________
Virt-test-devel mailing list
Virt-test-devel@redhat.com
https://www.redhat.com/mailman/listinfo/virt-test-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [virt-test][PATCH 4/7] virt: Adds named variants to Cartesian config.
  2013-04-16 14:16       ` Jiri Zupka
@ 2013-04-17  2:47         ` Alex Jia
  2013-05-03 15:54           ` virt: New version " Jiri Zupka
  0 siblings, 1 reply; 18+ messages in thread
From: Alex Jia @ 2013-04-17  2:47 UTC (permalink / raw)
  To: Jiri Zupka; +Cc: kvm, virt-test-devel, pbonzini, kvm-autotest

Jiří, okay, got it and thanks.

-- 
Regards,     
Alex


----- Original Message -----
From: "Jiri Zupka" <jzupka@redhat.com>
To: "Alex Jia" <ajia@redhat.com>
Cc: virt-test-devel@redhat.com, kvm@vger.kernel.org, kvm-autotest@redhat.com, lmr@redhat.com, ldoktor@redhat.com, ehabkost@redhat.com, pbonzini@redhat.com
Sent: Tuesday, April 16, 2013 10:16:57 PM
Subject: Re: [Virt-test-devel] [virt-test][PATCH 4/7] virt: Adds named variants to Cartesian config.

Hi Alex,
  thanks again for review. I recognize now what you mean. I thought that
you another thread of mails. I was try it again with
https://github.com/autotest/virt-test/pull/255 and demo example works.

If you are interest in this feature. Check new version which I'll send in
future days. There will be some changes in syntax and will be added lexer
for better filtering.

regards,
  Jiří Župka



----- Original Message -----
> Hi Alex,
>   I hope you use "new" version of cart config in github
>   https://github.com/autotest/virt-test/pull/255.
> This was older RFC version of vart config. And I'm preparing new version
> based on communication with Eduardo and Pablo.
> 
> If you don't please loot at documentation
> https://github.com/autotest/virt-test/wiki/VirtTestDocumentation#wiki-id26
> This documentation says how it works now.
> 
> regards
>   Jiří Župka
> 
> ----- Original Message -----
> > On 03/30/2013 01:14 AM, Jiří Župka wrote:
> > > variants name=tests:
> > >    - wait:
> > >         run = "wait"
> > >         variants:
> > >           - long:
> > >              time = short_time
> > >           - short: long
> > >              time = logn_time
> > >    - test2:
> > >         run = "test1"
> > >
> > > variants name=virt_system:
> > >    - linux:
> > >    - windows_XP:
> > >
> > > variants name=host_os:
> > >    - linux:
> > >         image = linux
> > >    - windows_XP:
> > >         image = windows
> > >
> > > tests>wait.short:
> > >      shutdown = destroy
> > >
> > > only host_os>linux
> > Jiří , I pasted above above example into demo.cfg and ran it via
> > cartesian parser then I got the error "__main__.ParserError: 'variants'
> > is not allowed inside a conditional block
> > (libvirt/tests/cfg/demo.cfg:4)", any wrong with me? thanks.
> > 
> > 
> 

_______________________________________________
Virt-test-devel mailing list
Virt-test-devel@redhat.com
https://www.redhat.com/mailman/listinfo/virt-test-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* virt: New version Cartesian config
  2013-04-17  2:47         ` Alex Jia
@ 2013-05-03 15:54           ` Jiri Zupka
  2013-05-16  9:35             ` Jiri Zupka
  0 siblings, 1 reply; 18+ messages in thread
From: Jiri Zupka @ 2013-05-03 15:54 UTC (permalink / raw)
  To: ehabkost, pbonzini, lmr; +Cc: kvm-autotest, virt-test-devel, kvm

Hi,
  the new version of cart config is on github https://github.com/autotest/virt-test/pull/335
Please send me your comment and I'll try to change code to good shape if there is a problem.
I'll choose one big patch because there is almost no possibility split parser to parts.
Unittest is in some patch too. Because it should be in one patch with tested code.

In future I'll change comments to sphinx syntax.

Regards,
  Jiří Župka

----- Original Message -----
> Jiří, okay, got it and thanks.
> 
> --
> Regards,
> Alex
> 
> 
> ----- Original Message -----
> From: "Jiri Zupka" <jzupka@redhat.com>
> To: "Alex Jia" <ajia@redhat.com>
> Cc: virt-test-devel@redhat.com, kvm@vger.kernel.org, kvm-autotest@redhat.com,
> lmr@redhat.com, ldoktor@redhat.com, ehabkost@redhat.com, pbonzini@redhat.com
> Sent: Tuesday, April 16, 2013 10:16:57 PM
> Subject: Re: [Virt-test-devel] [virt-test][PATCH 4/7] virt: Adds named
> variants to Cartesian config.
> 
> Hi Alex,
>   thanks again for review. I recognize now what you mean. I thought that
> you another thread of mails. I was try it again with
> https://github.com/autotest/virt-test/pull/255 and demo example works.
> 
> If you are interest in this feature. Check new version which I'll send in
> future days. There will be some changes in syntax and will be added lexer
> for better filtering.
> 
> regards,
>   Jiří Župka
> 
> 
> 
> ----- Original Message -----
> > Hi Alex,
> >   I hope you use "new" version of cart config in github
> >   https://github.com/autotest/virt-test/pull/255.
> > This was older RFC version of vart config. And I'm preparing new version
> > based on communication with Eduardo and Pablo.
> > 
> > If you don't please loot at documentation
> > https://github.com/autotest/virt-test/wiki/VirtTestDocumentation#wiki-id26
> > This documentation says how it works now.
> > 
> > regards
> >   Jiří Župka
> > 
> > ----- Original Message -----
> > > On 03/30/2013 01:14 AM, Jiří Župka wrote:
> > > > variants name=tests:
> > > >    - wait:
> > > >         run = "wait"
> > > >         variants:
> > > >           - long:
> > > >              time = short_time
> > > >           - short: long
> > > >              time = logn_time
> > > >    - test2:
> > > >         run = "test1"
> > > >
> > > > variants name=virt_system:
> > > >    - linux:
> > > >    - windows_XP:
> > > >
> > > > variants name=host_os:
> > > >    - linux:
> > > >         image = linux
> > > >    - windows_XP:
> > > >         image = windows
> > > >
> > > > tests>wait.short:
> > > >      shutdown = destroy
> > > >
> > > > only host_os>linux
> > > Jiří , I pasted above above example into demo.cfg and ran it via
> > > cartesian parser then I got the error "__main__.ParserError: 'variants'
> > > is not allowed inside a conditional block
> > > (libvirt/tests/cfg/demo.cfg:4)", any wrong with me? thanks.
> > > 
> > > 
> > 
> 
> 

_______________________________________________
Virt-test-devel mailing list
Virt-test-devel@redhat.com
https://www.redhat.com/mailman/listinfo/virt-test-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: virt: New version Cartesian config
  2013-05-03 15:54           ` virt: New version " Jiri Zupka
@ 2013-05-16  9:35             ` Jiri Zupka
  0 siblings, 0 replies; 18+ messages in thread
From: Jiri Zupka @ 2013-05-16  9:35 UTC (permalink / raw)
  To: ehabkost, pbonzini, lmr; +Cc: kvm-autotest, virt-test-devel, kvm

Hi,
  I have sent email about new Cart config update few days ago but nobody did  respond to on it.
Could you look at new cart config? Mainly Eduardo.

Have a nice day,
  Jiří Župka

----- Original Message -----
> Hi,
>   the new version of cart config is on github
>   https://github.com/autotest/virt-test/pull/335
> Please send me your comment and I'll try to change code to good shape if
> there is a problem.
> I'll choose one big patch because there is almost no possibility split parser
> to parts.
> Unittest is in some patch too. Because it should be in one patch with tested
> code.
> 
> In future I'll change comments to sphinx syntax.
> 
> Regards,
>   Jiří Župka
> 
> ----- Original Message -----
> > Jiří, okay, got it and thanks.
> > 
> > --
> > Regards,
> > Alex
> > 
> > 
> > ----- Original Message -----
> > From: "Jiri Zupka" <jzupka@redhat.com>
> > To: "Alex Jia" <ajia@redhat.com>
> > Cc: virt-test-devel@redhat.com, kvm@vger.kernel.org,
> > kvm-autotest@redhat.com,
> > lmr@redhat.com, ldoktor@redhat.com, ehabkost@redhat.com,
> > pbonzini@redhat.com
> > Sent: Tuesday, April 16, 2013 10:16:57 PM
> > Subject: Re: [Virt-test-devel] [virt-test][PATCH 4/7] virt: Adds named
> > variants to Cartesian config.
> > 
> > Hi Alex,
> >   thanks again for review. I recognize now what you mean. I thought that
> > you another thread of mails. I was try it again with
> > https://github.com/autotest/virt-test/pull/255 and demo example works.
> > 
> > If you are interest in this feature. Check new version which I'll send in
> > future days. There will be some changes in syntax and will be added lexer
> > for better filtering.
> > 
> > regards,
> >   Jiří Župka
> > 
> > 
> > 
> > ----- Original Message -----
> > > Hi Alex,
> > >   I hope you use "new" version of cart config in github
> > >   https://github.com/autotest/virt-test/pull/255.
> > > This was older RFC version of vart config. And I'm preparing new version
> > > based on communication with Eduardo and Pablo.
> > > 
> > > If you don't please loot at documentation
> > > https://github.com/autotest/virt-test/wiki/VirtTestDocumentation#wiki-id26
> > > This documentation says how it works now.
> > > 
> > > regards
> > >   Jiří Župka
> > > 
> > > ----- Original Message -----
> > > > On 03/30/2013 01:14 AM, Jiří Župka wrote:
> > > > > variants name=tests:
> > > > >    - wait:
> > > > >         run = "wait"
> > > > >         variants:
> > > > >           - long:
> > > > >              time = short_time
> > > > >           - short: long
> > > > >              time = logn_time
> > > > >    - test2:
> > > > >         run = "test1"
> > > > >
> > > > > variants name=virt_system:
> > > > >    - linux:
> > > > >    - windows_XP:
> > > > >
> > > > > variants name=host_os:
> > > > >    - linux:
> > > > >         image = linux
> > > > >    - windows_XP:
> > > > >         image = windows
> > > > >
> > > > > tests>wait.short:
> > > > >      shutdown = destroy
> > > > >
> > > > > only host_os>linux
> > > > Jiří , I pasted above above example into demo.cfg and ran it via
> > > > cartesian parser then I got the error "__main__.ParserError: 'variants'
> > > > is not allowed inside a conditional block
> > > > (libvirt/tests/cfg/demo.cfg:4)", any wrong with me? thanks.
> > > > 
> > > > 
> > > 
> > 
> > 
> 

_______________________________________________
Virt-test-devel mailing list
Virt-test-devel@redhat.com
https://www.redhat.com/mailman/listinfo/virt-test-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2013-05-16  9:35 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-29 17:14 [virt-test] virt: Cartesian config update v3 Jiří Župka
2013-03-29 17:14 ` [virt-test][PATCH 1/7] virt: Make Cartesian config more verbose Jiří Župka
2013-03-29 17:14 ` [virt-test][PATCH 2/7] virt: Update cartesian config unittest Jiří Župka
2013-03-29 17:14 ` [virt-test][PATCH 3/7] virt: Adds formal definition for Cartesian config Jiří Župka
2013-03-29 17:14 ` [virt-test][PATCH 4/7] virt: Adds named variants to " Jiří Župka
2013-04-01 14:30   ` Eduardo Habkost
2013-04-04 16:14     ` Jiri Zupka
2013-04-16  6:50   ` Alex Jia
2013-04-16 12:03     ` Jiri Zupka
2013-04-16 14:16       ` Jiri Zupka
2013-04-17  2:47         ` Alex Jia
2013-05-03 15:54           ` virt: New version " Jiri Zupka
2013-05-16  9:35             ` Jiri Zupka
2013-03-29 17:14 ` [virt-test][PATCH 5/7] virt: Update Cartesian config unittest named variants Jiří Župka
2013-04-01 14:21   ` Eduardo Habkost
2013-03-29 17:14 ` [virt-test][PATCH 6/7] virt: Adds possibility filter defaults variant from variants Jiří Župka
2013-04-01 14:40   ` Eduardo Habkost
2013-03-29 17:14 ` [virt-test][PATCH 7/7] virt: Update Cartesian config unittest default variants Jiří Župka

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.