All of lore.kernel.org
 help / color / mirror / Atom feed
* [Fuego] [PATCH] ftc: add support for tguid matching in where clauses
@ 2018-04-18  3:38 Tim.Bird
  2018-04-19  1:12 ` Daniel Sangorrin
  0 siblings, 1 reply; 2+ messages in thread
From: Tim.Bird @ 2018-04-18  3:38 UTC (permalink / raw)
  To: Tim.Bird, daniel.sangorrin, fuego

> -----Original Message-----
> From: Tim Bird
> > -----Original Message-----
> > From: Daniel Sangorrin
> >
> > Note: it would be nice to use the tguid in the where clause.
> 
> Indeed.  I'll take a look at this and see if I can add it.

Here's an attempt at something ...
Hope it's useful!

 -- Tim

----
Where clauses are used to filter results in ftc list-runs and
ftc gen-report.  Add support for using 'tguid' and 'tguid:result'
as where-clause arguments.  This allows fun stuff like:

$ ftc gen-report --where "test=LTP,tguid:result=FAIL"
$ ftc gen-report --where "test=Dhrystone,tguid:result<15000000"
$ ftc gen-report --where "tguid=~[DW].*Score"
$ ftc gen-report --where "tguid=~.*udp.*"

Signed-off-by: Tim Bird <tim.bird@sony.com>
---
 engine/scripts/ftc | 109 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 87 insertions(+), 22 deletions(-)

diff --git a/engine/scripts/ftc b/engine/scripts/ftc
index 4574eba..5b4d23d 100755
--- a/engine/scripts/ftc
+++ b/engine/scripts/ftc
@@ -85,14 +85,16 @@ where_help = \
   to filter the list of runs. Each where clause is separated by a comma.
   A 'where clause' consists of a field_name, an operator and a value.
   Allowed field names are: test, type, spec, board, start_time, result,
-  batch_id, status, and build_number.
+  batch_id, status, build_number, tguid, and tguid:result.
   Allowed operators are: '=','<','<=','>','>=','!=','=~'.  The '=~' operator
   means the value is a regular expression to match, for the indicated field.
   Here are some example where options:
      --where test=LTP
      --where test=bonnie,board=beaglebone
      --where "start_time>2 hours ago"
-     --where batch_id=12"""
+     --where batch_id=12
+     --where tguid=~.*udp.*
+     --where tguid:result=FAIL"""
 
 # format for command_help mapping with: key=name, value=(summary, long description)
 command_help = {
@@ -963,6 +965,9 @@ class run_class:
             except:
                 return ""
 
+    def __repr__(self):
+       return self.run_id
+
 
 # return a map of {'<board_name>': board_instance }
 def get_fuego_boards(conf):
@@ -1909,6 +1914,36 @@ class where_class:
     def __repr__(self):
        return "where(%s, %s, %s)" % (self.field_name, self.op, self.value)
 
+    def check_value(self, run_value):
+        if self.op == "=":
+            return run_value == self.value
+        elif self.op == "!=":
+            return run_value != self.value
+        elif self.op == "=~":
+            return re.match(self.value, run_value)
+        elif self.op == "<=":
+            try:
+                return float(run_value) <= float(self.value)
+            except ValueError:
+                return False
+        elif self.op == ">=":
+            try:
+                return float(run_value) >= float(self.value)
+            except ValueError:
+                return False
+        elif self.op == "<":
+            try:
+                return float(run_value) < float(self.value)
+            except ValueError:
+                return False
+        elif self.op == ">":
+            try:
+                return float(run_value) > float(self.value)
+            except ValueError:
+                return False
+
+        return False
+
     def match(self, run):
         # some fields can be found without loading the run.json file
         # examples are: "test", "type", "spec", "board", "num"
@@ -1928,25 +1963,39 @@ class where_class:
             try:
                 run_value = run.__dict__[self.field_name]
             except:
-                print("Error: did not find field '%s' in loaded run data for run %s" % (self.field_name, run.run_id))
-                return False
+                pass
 
-        if self.op == "=":
-            return run_value == self.value
-        elif self.op == "!=":
-            return run_value != self.value
-        elif self.op == "=~":
-            return re.match(self.value, run_value)
-        elif self.op == "<=":
-            return float(run_value) <= float(self.value)
-        elif self.op == ">=":
-            return float(run_value) >= float(self.value)
-        elif self.op == "<":
-            return float(run_value) < float(self.value)
-        elif self.op == ">":
-            return float(run_value) > float(self.value)
+        if found:
+            return self.check_value(run_value)
+
+        # check run data for tguid and tguid:result (on each tguid)
+        if self.field_name=="tguid":
+            cur_tguid = run.next_tguid("")
+            while cur_tguid:
+                if self.check_value(cur_tguid):
+                    return True
+                cur_tguid = run.next_tguid(cur_tguid)
+            return False
+
+        if self.field_name=="tguid:result":
+            cur_tguid = run.next_tguid("")
+            while cur_tguid:
+                if self.check_value(run.get_field("result", cur_tguid)):
+                    return True
+                cur_tguid = run.next_tguid(cur_tguid)
+            return False
+
+        print("Error: did not find field '%s' in loaded run data for run %s" % (self.field_name, run.run_id))
         return False
 
+    def match_tguid(self, run, tguid):
+        # check run data for tguid match
+        if self.field_name=="tguid":
+            return self.check_value(tguid)
+
+        if self.field_name=="tguid:result":
+            return self.check_value(run.get_field("result", tguid))
+
 
 # returns a where_list (list of where tuples)
 # each where tuple is (field_name, operation, value)
@@ -1956,7 +2005,7 @@ def parse_where(where_string):
     op_list = ["!=", "=~", "<=", ">=", "=", "<", ">"]
     #field_list = ["testcase", "test","type","spec","board","host","since"]
     field_list = ["test", "type", "spec", "board", "start_time", "result",
-        "batch_id", "status", "build_number"]
+            "batch_id", "status", "build_number", "tguid", "tguid:result"]
     where_list = []
     for clause in where_string.split(","):
         where = None
@@ -2058,7 +2107,7 @@ def get_report_header_data(run_list, run_map, header_fields):
 # list of field names.
 # In each subsequent list is a list of values corresponding to the
 # requested fields, from the run data
-def get_report_data(run_list, run_map, fields):
+def get_report_data(run_list, run_map, fields, where_list):
     # first element is list of field names
     report_data = [fields]
 
@@ -2071,6 +2120,11 @@ def get_report_data(run_list, run_map, fields):
     run.get_run_data_from_json_file()
     cur_tguid = ""
 
+    where_list_has_tguid_field = False
+    for where in where_list:
+        if where.field_name.startswith("tguid"):
+            where_list_has_tguid_field = True
+
     done = False
     while not done:
         cur_tguid = run.next_tguid(cur_tguid)
@@ -2091,7 +2145,17 @@ def get_report_data(run_list, run_map, fields):
             if cur_tguid == "default":
                 continue
 
-        # at this point, we have a (run, tguid) with data
+        # at this point, we have a (run, cur_tguid) with data
+
+        # check to see if we need to filter this entry
+        if where_list_has_tguid_field:
+            match = True
+            for where in where_list:
+                if where.field_name.startswith("tguid"):
+                    if not where.match_tguid(run, cur_tguid):
+                        match = False
+            if not match:
+                continue
 
         # get the values of the fields for this entry
         value_list = []
@@ -2387,6 +2451,7 @@ def do_gen_report(conf, options):
         where_list = parse_where(where_str)
         run_list = filter_runs(run_map, where_list)
     else:
+        where_list = []
         run_list = run_map.keys()
 
     if not run_list:
@@ -2455,7 +2520,7 @@ def do_gen_report(conf, options):
 
     # get data for report
     header_data = get_report_header_data(run_list, run_map, header_fields)
-    report_data = get_report_data(run_list, run_map, fields)
+    report_data = get_report_data(run_list, run_map, fields, where_list)
 
     if fmt == "txt":
         report = gen_txt_report(header_data, report_data)
-- 
2.1.4


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

* Re: [Fuego] [PATCH] ftc: add support for tguid matching in where clauses
  2018-04-18  3:38 [Fuego] [PATCH] ftc: add support for tguid matching in where clauses Tim.Bird
@ 2018-04-19  1:12 ` Daniel Sangorrin
  0 siblings, 0 replies; 2+ messages in thread
From: Daniel Sangorrin @ 2018-04-19  1:12 UTC (permalink / raw)
  To: Tim.Bird, fuego

> > -----Original Message-----
> > From: Tim Bird
> > > -----Original Message-----
> > > From: Daniel Sangorrin
> > >
> > > Note: it would be nice to use the tguid in the where clause.
> >
> > Indeed.  I'll take a look at this and see if I can add it.
> 
> Here's an attempt at something ...
> Hope it's useful!

Wow thanks a lot for this!! it works well and it's super useful.

Thanks,
Daniel
 
> ----
> Where clauses are used to filter results in ftc list-runs and
> ftc gen-report.  Add support for using 'tguid' and 'tguid:result'
> as where-clause arguments.  This allows fun stuff like:
> 
> $ ftc gen-report --where "test=LTP,tguid:result=FAIL"
> $ ftc gen-report --where "test=Dhrystone,tguid:result<15000000"
> $ ftc gen-report --where "tguid=~[DW].*Score"
> $ ftc gen-report --where "tguid=~.*udp.*"
> 
> Signed-off-by: Tim Bird <tim.bird@sony.com>
> ---
>  engine/scripts/ftc | 109
> ++++++++++++++++++++++++++++++++++++++++++-----------
>  1 file changed, 87 insertions(+), 22 deletions(-)
> 
> diff --git a/engine/scripts/ftc b/engine/scripts/ftc
> index 4574eba..5b4d23d 100755
> --- a/engine/scripts/ftc
> +++ b/engine/scripts/ftc
> @@ -85,14 +85,16 @@ where_help = \
>    to filter the list of runs. Each where clause is separated by a comma.
>    A 'where clause' consists of a field_name, an operator and a value.
>    Allowed field names are: test, type, spec, board, start_time, result,
> -  batch_id, status, and build_number.
> +  batch_id, status, build_number, tguid, and tguid:result.
>    Allowed operators are: '=','<','<=','>','>=','!=','=~'.  The '=~' operator
>    means the value is a regular expression to match, for the indicated field.
>    Here are some example where options:
>       --where test=LTP
>       --where test=bonnie,board=beaglebone
>       --where "start_time>2 hours ago"
> -     --where batch_id=12"""
> +     --where batch_id=12
> +     --where tguid=~.*udp.*
> +     --where tguid:result=FAIL"""
> 
>  # format for command_help mapping with: key=name, value=(summary, long
> description)
>  command_help = {
> @@ -963,6 +965,9 @@ class run_class:
>              except:
>                  return ""
> 
> +    def __repr__(self):
> +       return self.run_id
> +
> 
>  # return a map of {'<board_name>': board_instance }
>  def get_fuego_boards(conf):
> @@ -1909,6 +1914,36 @@ class where_class:
>      def __repr__(self):
>         return "where(%s, %s, %s)" % (self.field_name, self.op, self.value)
> 
> +    def check_value(self, run_value):
> +        if self.op == "=":
> +            return run_value == self.value
> +        elif self.op == "!=":
> +            return run_value != self.value
> +        elif self.op == "=~":
> +            return re.match(self.value, run_value)
> +        elif self.op == "<=":
> +            try:
> +                return float(run_value) <= float(self.value)
> +            except ValueError:
> +                return False
> +        elif self.op == ">=":
> +            try:
> +                return float(run_value) >= float(self.value)
> +            except ValueError:
> +                return False
> +        elif self.op == "<":
> +            try:
> +                return float(run_value) < float(self.value)
> +            except ValueError:
> +                return False
> +        elif self.op == ">":
> +            try:
> +                return float(run_value) > float(self.value)
> +            except ValueError:
> +                return False
> +
> +        return False
> +
>      def match(self, run):
>          # some fields can be found without loading the run.json file
>          # examples are: "test", "type", "spec", "board", "num"
> @@ -1928,25 +1963,39 @@ class where_class:
>              try:
>                  run_value = run.__dict__[self.field_name]
>              except:
> -                print("Error: did not find field '%s' in loaded run data for run %s" %
> (self.field_name, run.run_id))
> -                return False
> +                pass
> 
> -        if self.op == "=":
> -            return run_value == self.value
> -        elif self.op == "!=":
> -            return run_value != self.value
> -        elif self.op == "=~":
> -            return re.match(self.value, run_value)
> -        elif self.op == "<=":
> -            return float(run_value) <= float(self.value)
> -        elif self.op == ">=":
> -            return float(run_value) >= float(self.value)
> -        elif self.op == "<":
> -            return float(run_value) < float(self.value)
> -        elif self.op == ">":
> -            return float(run_value) > float(self.value)
> +        if found:
> +            return self.check_value(run_value)
> +
> +        # check run data for tguid and tguid:result (on each tguid)
> +        if self.field_name=="tguid":
> +            cur_tguid = run.next_tguid("")
> +            while cur_tguid:
> +                if self.check_value(cur_tguid):
> +                    return True
> +                cur_tguid = run.next_tguid(cur_tguid)
> +            return False
> +
> +        if self.field_name=="tguid:result":
> +            cur_tguid = run.next_tguid("")
> +            while cur_tguid:
> +                if self.check_value(run.get_field("result", cur_tguid)):
> +                    return True
> +                cur_tguid = run.next_tguid(cur_tguid)
> +            return False
> +
> +        print("Error: did not find field '%s' in loaded run data for run %s" %
> (self.field_name, run.run_id))
>          return False
> 
> +    def match_tguid(self, run, tguid):
> +        # check run data for tguid match
> +        if self.field_name=="tguid":
> +            return self.check_value(tguid)
> +
> +        if self.field_name=="tguid:result":
> +            return self.check_value(run.get_field("result", tguid))
> +
> 
>  # returns a where_list (list of where tuples)
>  # each where tuple is (field_name, operation, value)
> @@ -1956,7 +2005,7 @@ def parse_where(where_string):
>      op_list = ["!=", "=~", "<=", ">=", "=", "<", ">"]
>      #field_list = ["testcase", "test","type","spec","board","host","since"]
>      field_list = ["test", "type", "spec", "board", "start_time", "result",
> -        "batch_id", "status", "build_number"]
> +            "batch_id", "status", "build_number", "tguid", "tguid:result"]
>      where_list = []
>      for clause in where_string.split(","):
>          where = None
> @@ -2058,7 +2107,7 @@ def get_report_header_data(run_list, run_map,
> header_fields):
>  # list of field names.
>  # In each subsequent list is a list of values corresponding to the
>  # requested fields, from the run data
> -def get_report_data(run_list, run_map, fields):
> +def get_report_data(run_list, run_map, fields, where_list):
>      # first element is list of field names
>      report_data = [fields]
> 
> @@ -2071,6 +2120,11 @@ def get_report_data(run_list, run_map, fields):
>      run.get_run_data_from_json_file()
>      cur_tguid = ""
> 
> +    where_list_has_tguid_field = False
> +    for where in where_list:
> +        if where.field_name.startswith("tguid"):
> +            where_list_has_tguid_field = True
> +
>      done = False
>      while not done:
>          cur_tguid = run.next_tguid(cur_tguid)
> @@ -2091,7 +2145,17 @@ def get_report_data(run_list, run_map, fields):
>              if cur_tguid == "default":
>                  continue
> 
> -        # at this point, we have a (run, tguid) with data
> +        # at this point, we have a (run, cur_tguid) with data
> +
> +        # check to see if we need to filter this entry
> +        if where_list_has_tguid_field:
> +            match = True
> +            for where in where_list:
> +                if where.field_name.startswith("tguid"):
> +                    if not where.match_tguid(run, cur_tguid):
> +                        match = False
> +            if not match:
> +                continue
> 
>          # get the values of the fields for this entry
>          value_list = []
> @@ -2387,6 +2451,7 @@ def do_gen_report(conf, options):
>          where_list = parse_where(where_str)
>          run_list = filter_runs(run_map, where_list)
>      else:
> +        where_list = []
>          run_list = run_map.keys()
> 
>      if not run_list:
> @@ -2455,7 +2520,7 @@ def do_gen_report(conf, options):
> 
>      # get data for report
>      header_data = get_report_header_data(run_list, run_map, header_fields)
> -    report_data = get_report_data(run_list, run_map, fields)
> +    report_data = get_report_data(run_list, run_map, fields, where_list)
> 
>      if fmt == "txt":
>          report = gen_txt_report(header_data, report_data)
> --
> 2.1.4
> 




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

end of thread, other threads:[~2018-04-19  1:12 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-18  3:38 [Fuego] [PATCH] ftc: add support for tguid matching in where clauses Tim.Bird
2018-04-19  1:12 ` Daniel Sangorrin

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.