From patchwork Fri Mar 29 17:14:04 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jiri Zupka X-Patchwork-Id: 2366181 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id D2450DFB79 for ; Fri, 29 Mar 2013 17:14:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755939Ab3C2ROT (ORCPT ); Fri, 29 Mar 2013 13:14:19 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53191 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754127Ab3C2ROS (ORCPT ); Fri, 29 Mar 2013 13:14:18 -0400 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r2THEIMD004960 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 29 Mar 2013 13:14:18 -0400 Received: from jzupka-pc.local.com (vpn1-6-43.ams2.redhat.com [10.36.6.43]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id r2THEDLw032179; Fri, 29 Mar 2013 13:14:16 -0400 From: =?UTF-8?q?Ji=C5=99=C3=AD=20=C5=BDupka?= To: virt-test-devel@redhat.com, kvm@vger.kernel.org, kvm-autotest@redhat.com, lmr@redhat.com, ldoktor@redhat.com, jzupka@redhat.com, ehabkost@redhat.com, pbonzini@redhat.com Subject: [virt-test][PATCH 1/7] virt: Make Cartesian config more verbose Date: Fri, 29 Mar 2013 18:14:04 +0100 Message-Id: <1364577250-2637-2-git-send-email-jzupka@redhat.com> In-Reply-To: <1364577250-2637-1-git-send-email-jzupka@redhat.com> References: <1364577250-2637-1-git-send-email-jzupka@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Signed-off-by: Ji?í Župka --- 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)