diff mbox series

[v6,08/11] qapi: add 'any' condition

Message ID 20210618102507.3761128-9-marcandre.lureau@redhat.com (mailing list archive)
State New, archived
Headers show
Series qapi: untie 'if' conditions from C preprocessor | expand

Commit Message

Marc-André Lureau June 18, 2021, 10:25 a.m. UTC
From: Marc-André Lureau <marcandre.lureau@redhat.com>

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 tests/unit/test-qmp-cmds.c              | 1 +
 scripts/qapi/common.py                  | 4 ++--
 scripts/qapi/expr.py                    | 6 +++---
 tests/qapi-schema/bad-if.err            | 2 +-
 tests/qapi-schema/doc-good.json         | 3 ++-
 tests/qapi-schema/doc-good.out          | 2 +-
 tests/qapi-schema/doc-good.txt          | 3 ++-
 tests/qapi-schema/enum-if-invalid.err   | 2 +-
 tests/qapi-schema/qapi-schema-test.json | 7 ++++++-
 tests/qapi-schema/qapi-schema-test.out  | 5 +++++
 10 files changed, 24 insertions(+), 11 deletions(-)

Comments

Markus Armbruster Aug. 3, 2021, 1:20 p.m. UTC | #1
marcandre.lureau@redhat.com writes:

> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  tests/unit/test-qmp-cmds.c              | 1 +
>  scripts/qapi/common.py                  | 4 ++--
>  scripts/qapi/expr.py                    | 6 +++---
>  tests/qapi-schema/bad-if.err            | 2 +-
>  tests/qapi-schema/doc-good.json         | 3 ++-
>  tests/qapi-schema/doc-good.out          | 2 +-
>  tests/qapi-schema/doc-good.txt          | 3 ++-
>  tests/qapi-schema/enum-if-invalid.err   | 2 +-
>  tests/qapi-schema/qapi-schema-test.json | 7 ++++++-
>  tests/qapi-schema/qapi-schema-test.out  | 5 +++++
>  10 files changed, 24 insertions(+), 11 deletions(-)
>
> diff --git a/tests/unit/test-qmp-cmds.c b/tests/unit/test-qmp-cmds.c
> index 1b0b7d99df..83efa39720 100644
> --- a/tests/unit/test-qmp-cmds.c
> +++ b/tests/unit/test-qmp-cmds.c
> @@ -51,6 +51,7 @@ FeatureStruct1 *qmp_test_features0(bool has_fs0, FeatureStruct0 *fs0,
>                                     bool has_cfs1, CondFeatureStruct1 *cfs1,
>                                     bool has_cfs2, CondFeatureStruct2 *cfs2,
>                                     bool has_cfs3, CondFeatureStruct3 *cfs3,
> +                                   bool has_cfs4, CondFeatureStruct4 *cfs4,
>                                     Error **errp)
>  {
>      return g_new0(FeatureStruct1, 1);
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 51463510c9..018d2f6996 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -207,7 +207,7 @@ def docgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str:
>          return ifcond
>  
>      oper, operands = next(iter(ifcond.items()))
> -    oper = {'all': ' and '}[oper]
> +    oper = {'all': ' and ', 'any': ' or '}[oper]
>      operands = [docgen_ifcond(o) for o in operands]
>      return '(' + oper.join(operands) + ')'
>  
> @@ -219,7 +219,7 @@ def cgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str:
>          return ifcond
>  
>      oper, operands = next(iter(ifcond.items()))
> -    oper = {'all': '&&'}[oper]
> +    oper = {'all': '&&', 'any': '||'}[oper]
>      operands = [cgen_ifcond(o) for o in operands]
>      return '(' + (') ' + oper + ' (').join(operands) + ')'
>  
> diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py
> index 3ee66c5f62..e10a803dc2 100644
> --- a/scripts/qapi/expr.py
> +++ b/scripts/qapi/expr.py
> @@ -296,16 +296,16 @@ def _check_if(cond: Union[str, object]) -> None:
>              raise QAPISemError(
>                  info,
>                  "'if' condition dict of %s must have one key: "
> -                "'all'" % source)
> +                "'all' or 'any'" % source)
>          check_keys(cond, info, "'if' condition", [],
> -                   ["all"])
> +                   ["all", "any"])
>  
>          oper, operands = next(iter(cond.items()))
>          if not operands:
>              raise QAPISemError(
>                  info, "'if' condition [] of %s is useless" % source)
>  
> -        if oper in ("all") and not isinstance(operands, list):
> +        if oper in ("all", "any") and not isinstance(operands, list):
>              raise QAPISemError(
>                  info, "'%s' condition of %s must be a list" % (oper, source))
>          for operand in operands:
> diff --git a/tests/qapi-schema/bad-if.err b/tests/qapi-schema/bad-if.err
> index 8278c49368..3624e79b0c 100644
> --- a/tests/qapi-schema/bad-if.err
> +++ b/tests/qapi-schema/bad-if.err
> @@ -1,3 +1,3 @@
>  bad-if.json: In struct 'TestIfStruct':
>  bad-if.json:2: 'if' condition has unknown key 'value'
> -Valid keys are 'all'.
> +Valid keys are 'all', 'any'.
> diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json
> index 25b1053e8a..a67d4d9467 100644
> --- a/tests/qapi-schema/doc-good.json
> +++ b/tests/qapi-schema/doc-good.json
> @@ -103,7 +103,8 @@
>    'features': [ 'union-feat1' ],
>    'base': 'Base',
>    'discriminator': 'base1',
> -  'data': { 'one': 'Variant1', 'two': { 'type': 'Variant2', 'if': 'IFTWO' } } }
> +  'data': { 'one': 'Variant1', 'two': { 'type': 'Variant2',
> +                                        'if': { 'any': ['IFONE', 'IFTWO'] } } } }

Easier to read:

     'data': { 'one': 'Variant1',
               'two': { 'type': 'Variant2',
                        'if': { 'any': ['IFONE', 'IFTWO'] } } } }

>  
>  ##
>  # @SugaredUnion:
> diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
> index 689d084f3a..c44c346ec8 100644
> --- a/tests/qapi-schema/doc-good.out
> +++ b/tests/qapi-schema/doc-good.out
> @@ -30,7 +30,7 @@ object Object
>      tag base1
>      case one: Variant1
>      case two: Variant2
> -        if IFTWO
> +        if OrderedDict([('any', ['IFONE', 'IFTWO'])])
>      feature union-feat1
>  object q_obj_Variant1-wrapper
>      member data: Variant1 optional=False
> diff --git a/tests/qapi-schema/doc-good.txt b/tests/qapi-schema/doc-good.txt
> index 4490108cb7..251e9b746c 100644
> --- a/tests/qapi-schema/doc-good.txt
> +++ b/tests/qapi-schema/doc-good.txt
> @@ -120,7 +120,8 @@ Members
>  
>  The members of "Base"
>  The members of "Variant1" when "base1" is ""one""
> -The members of "Variant2" when "base1" is ""two"" (**If: **"IFTWO")
> +The members of "Variant2" when "base1" is ""two"" (**If: **"(IFONE or
> +IFTWO)")
>  
>  Features
>  ~~~~~~~~
> diff --git a/tests/qapi-schema/enum-if-invalid.err b/tests/qapi-schema/enum-if-invalid.err
> index df305cd79f..b96d94c48a 100644
> --- a/tests/qapi-schema/enum-if-invalid.err
> +++ b/tests/qapi-schema/enum-if-invalid.err
> @@ -1,3 +1,3 @@
>  enum-if-invalid.json: In enum 'TestIfEnum':
>  enum-if-invalid.json:2: 'if' condition has unknown key 'val'
> -Valid keys are 'all'.
> +Valid keys are 'all', 'any'.
> diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
> index f2e0fff51f..252fd8cc86 100644
> --- a/tests/qapi-schema/qapi-schema-test.json
> +++ b/tests/qapi-schema/qapi-schema-test.json
> @@ -290,6 +290,10 @@
>    'features': [ { 'name': 'feature1',
>                    'if': { 'all': [ 'defined(TEST_IF_COND_1)',
>                                     'defined(TEST_IF_COND_2)'] } } ] }
> +{ 'struct': 'CondFeatureStruct4',
> +  'data': { 'foo': 'int' },
> +  'features': [ { 'name': 'feature1', 'if': {'any': ['defined(TEST_IF_COND_1)',
> +                                                     'defined(TEST_IF_COND_2)'] } } ] }

Easier to read:

   { 'struct': 'CondFeatureStruct4',
     'data': { 'foo': 'int' },
     'features': [ { 'name': 'feature1',
                     'if': {'any': ['defined(TEST_IF_COND_1)',
                                    'defined(TEST_IF_COND_2)'] } } ] }

>  
>  { 'enum': 'FeatureEnum1',
>    'data': [ 'eins', 'zwei', 'drei' ],
> @@ -313,7 +317,8 @@
>              '*fs4': 'FeatureStruct4',
>              '*cfs1': 'CondFeatureStruct1',
>              '*cfs2': 'CondFeatureStruct2',
> -            '*cfs3': 'CondFeatureStruct3' },
> +            '*cfs3': 'CondFeatureStruct3',
> +            '*cfs4': 'CondFeatureStruct4' },
>    'returns': 'FeatureStruct1',
>    'features': [] }
>  
> diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
> index 6a1b3aa341..e5625f2542 100644
> --- a/tests/qapi-schema/qapi-schema-test.out
> +++ b/tests/qapi-schema/qapi-schema-test.out
> @@ -390,6 +390,10 @@ object CondFeatureStruct3
>      member foo: int optional=False
>      feature feature1
>          if OrderedDict([('all', ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)'])])
> +object CondFeatureStruct4
> +    member foo: int optional=False
> +    feature feature1
> +        if OrderedDict([('any', ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)'])])
>  enum FeatureEnum1
>      member eins
>      member zwei
> @@ -417,6 +421,7 @@ object q_obj_test-features0-arg
>      member cfs1: CondFeatureStruct1 optional=True
>      member cfs2: CondFeatureStruct2 optional=True
>      member cfs3: CondFeatureStruct3 optional=True
> +    member cfs4: CondFeatureStruct4 optional=True
>  command test-features0 q_obj_test-features0-arg -> FeatureStruct1
>      gen=True success_response=True boxed=False oob=False preconfig=False
>  command test-command-features1 None -> None
diff mbox series

Patch

diff --git a/tests/unit/test-qmp-cmds.c b/tests/unit/test-qmp-cmds.c
index 1b0b7d99df..83efa39720 100644
--- a/tests/unit/test-qmp-cmds.c
+++ b/tests/unit/test-qmp-cmds.c
@@ -51,6 +51,7 @@  FeatureStruct1 *qmp_test_features0(bool has_fs0, FeatureStruct0 *fs0,
                                    bool has_cfs1, CondFeatureStruct1 *cfs1,
                                    bool has_cfs2, CondFeatureStruct2 *cfs2,
                                    bool has_cfs3, CondFeatureStruct3 *cfs3,
+                                   bool has_cfs4, CondFeatureStruct4 *cfs4,
                                    Error **errp)
 {
     return g_new0(FeatureStruct1, 1);
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 51463510c9..018d2f6996 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -207,7 +207,7 @@  def docgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str:
         return ifcond
 
     oper, operands = next(iter(ifcond.items()))
-    oper = {'all': ' and '}[oper]
+    oper = {'all': ' and ', 'any': ' or '}[oper]
     operands = [docgen_ifcond(o) for o in operands]
     return '(' + oper.join(operands) + ')'
 
@@ -219,7 +219,7 @@  def cgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str:
         return ifcond
 
     oper, operands = next(iter(ifcond.items()))
-    oper = {'all': '&&'}[oper]
+    oper = {'all': '&&', 'any': '||'}[oper]
     operands = [cgen_ifcond(o) for o in operands]
     return '(' + (') ' + oper + ' (').join(operands) + ')'
 
diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py
index 3ee66c5f62..e10a803dc2 100644
--- a/scripts/qapi/expr.py
+++ b/scripts/qapi/expr.py
@@ -296,16 +296,16 @@  def _check_if(cond: Union[str, object]) -> None:
             raise QAPISemError(
                 info,
                 "'if' condition dict of %s must have one key: "
-                "'all'" % source)
+                "'all' or 'any'" % source)
         check_keys(cond, info, "'if' condition", [],
-                   ["all"])
+                   ["all", "any"])
 
         oper, operands = next(iter(cond.items()))
         if not operands:
             raise QAPISemError(
                 info, "'if' condition [] of %s is useless" % source)
 
-        if oper in ("all") and not isinstance(operands, list):
+        if oper in ("all", "any") and not isinstance(operands, list):
             raise QAPISemError(
                 info, "'%s' condition of %s must be a list" % (oper, source))
         for operand in operands:
diff --git a/tests/qapi-schema/bad-if.err b/tests/qapi-schema/bad-if.err
index 8278c49368..3624e79b0c 100644
--- a/tests/qapi-schema/bad-if.err
+++ b/tests/qapi-schema/bad-if.err
@@ -1,3 +1,3 @@ 
 bad-if.json: In struct 'TestIfStruct':
 bad-if.json:2: 'if' condition has unknown key 'value'
-Valid keys are 'all'.
+Valid keys are 'all', 'any'.
diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json
index 25b1053e8a..a67d4d9467 100644
--- a/tests/qapi-schema/doc-good.json
+++ b/tests/qapi-schema/doc-good.json
@@ -103,7 +103,8 @@ 
   'features': [ 'union-feat1' ],
   'base': 'Base',
   'discriminator': 'base1',
-  'data': { 'one': 'Variant1', 'two': { 'type': 'Variant2', 'if': 'IFTWO' } } }
+  'data': { 'one': 'Variant1', 'two': { 'type': 'Variant2',
+                                        'if': { 'any': ['IFONE', 'IFTWO'] } } } }
 
 ##
 # @SugaredUnion:
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index 689d084f3a..c44c346ec8 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -30,7 +30,7 @@  object Object
     tag base1
     case one: Variant1
     case two: Variant2
-        if IFTWO
+        if OrderedDict([('any', ['IFONE', 'IFTWO'])])
     feature union-feat1
 object q_obj_Variant1-wrapper
     member data: Variant1 optional=False
diff --git a/tests/qapi-schema/doc-good.txt b/tests/qapi-schema/doc-good.txt
index 4490108cb7..251e9b746c 100644
--- a/tests/qapi-schema/doc-good.txt
+++ b/tests/qapi-schema/doc-good.txt
@@ -120,7 +120,8 @@  Members
 
 The members of "Base"
 The members of "Variant1" when "base1" is ""one""
-The members of "Variant2" when "base1" is ""two"" (**If: **"IFTWO")
+The members of "Variant2" when "base1" is ""two"" (**If: **"(IFONE or
+IFTWO)")
 
 Features
 ~~~~~~~~
diff --git a/tests/qapi-schema/enum-if-invalid.err b/tests/qapi-schema/enum-if-invalid.err
index df305cd79f..b96d94c48a 100644
--- a/tests/qapi-schema/enum-if-invalid.err
+++ b/tests/qapi-schema/enum-if-invalid.err
@@ -1,3 +1,3 @@ 
 enum-if-invalid.json: In enum 'TestIfEnum':
 enum-if-invalid.json:2: 'if' condition has unknown key 'val'
-Valid keys are 'all'.
+Valid keys are 'all', 'any'.
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index f2e0fff51f..252fd8cc86 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -290,6 +290,10 @@ 
   'features': [ { 'name': 'feature1',
                   'if': { 'all': [ 'defined(TEST_IF_COND_1)',
                                    'defined(TEST_IF_COND_2)'] } } ] }
+{ 'struct': 'CondFeatureStruct4',
+  'data': { 'foo': 'int' },
+  'features': [ { 'name': 'feature1', 'if': {'any': ['defined(TEST_IF_COND_1)',
+                                                     'defined(TEST_IF_COND_2)'] } } ] }
 
 { 'enum': 'FeatureEnum1',
   'data': [ 'eins', 'zwei', 'drei' ],
@@ -313,7 +317,8 @@ 
             '*fs4': 'FeatureStruct4',
             '*cfs1': 'CondFeatureStruct1',
             '*cfs2': 'CondFeatureStruct2',
-            '*cfs3': 'CondFeatureStruct3' },
+            '*cfs3': 'CondFeatureStruct3',
+            '*cfs4': 'CondFeatureStruct4' },
   'returns': 'FeatureStruct1',
   'features': [] }
 
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 6a1b3aa341..e5625f2542 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -390,6 +390,10 @@  object CondFeatureStruct3
     member foo: int optional=False
     feature feature1
         if OrderedDict([('all', ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)'])])
+object CondFeatureStruct4
+    member foo: int optional=False
+    feature feature1
+        if OrderedDict([('any', ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)'])])
 enum FeatureEnum1
     member eins
     member zwei
@@ -417,6 +421,7 @@  object q_obj_test-features0-arg
     member cfs1: CondFeatureStruct1 optional=True
     member cfs2: CondFeatureStruct2 optional=True
     member cfs3: CondFeatureStruct3 optional=True
+    member cfs4: CondFeatureStruct4 optional=True
 command test-features0 q_obj_test-features0-arg -> FeatureStruct1
     gen=True success_response=True boxed=False oob=False preconfig=False
 command test-command-features1 None -> None