QAPI patches patches for 2021-10-27
-----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEENUvIs9frKmtoZ05fOHC0AOuRhlMFAmF5bpISHGFybWJydUBy ZWRoYXQuY29tAAoJEDhwtADrkYZThBsP/jgLAry80cEd+xZUTQTfQDfWEB9ScE0R V/yV385klxl/yXf7D7pzel89fflu8V1sjSHn6x29HbOTHWctG8u8LtRO4lBqooRq yG4EZ7xWChchrjyBzeEtL/eHBJWktPVqvK7U2Z+2jCqM5gy1xgCsMzqPpPraOHoi Z3g50JKYQE+JVkoqzzry+yRckHtQsOF2CR+QQGpf+e3xvUrOnOyukGftr3Cfppcg fMkb70mPknHMDepHSYQop7n7LPIbZuX8nbV0uFfGShMyiJa0zSzfWEfWhPxRQgwv mMuV0yzxnXE0EP515rQ7HVRaYUopmMJaTVa7gBRMu5kh16/7eFXBjs/vSUlV1reH ZkNefKIsLpFlgFMOLbEVAPF3/VIlFkO1IQI+UvNz5FDKCR65YLUTZ0D89+XCQqlp zi8NXDQ+IhHIBRSMsCFgLClzmDrXeDW6g3IEJUvjP+vV6IqmbiU6TfvOkMurF+KI 0QEH3LfKIWU/vkvecWd2EjDWoGatsqtQm5GMBEUHLnrQyekYc0k1f8W230EG2mKJ 19Eh/R6aYc9K4Vgx0OgfZjxBh3GARrOO7TEnaLQNeClBR8UKGqP0iVtYdVkroyIB ui2U/hiRCi115Wj4y4F7M6er7MbkxR5iBy/8H7H96hOG5vFC9UyagUw1L6bsaRDt EMAnG+4daNgX =Ff93 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-10-27' into staging QAPI patches patches for 2021-10-27 # gpg: Signature made Wed 27 Oct 2021 08:21:54 AM PDT # gpg: using RSA key 354BC8B3D7EB2A6B68674E5F3870B400EB918653 # gpg: issuer "armbru@redhat.com" # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" [full] # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" [full] * remotes/armbru/tags/pull-qapi-2021-10-27: qapi: Implement deprecated-input={reject,crash} for enum values qapi: Move compat policy from QObject to generic visitor qapi: Add feature flags to enum members qapi: Enable enum member introspection to show more than name qapi: Improve input_type_enum()'s error message Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
5c49c6c241
|
@ -228,6 +228,12 @@ Use the more generic commands ``block-export-add`` and ``block-export-del``
|
|||
instead. As part of this deprecation, where ``nbd-server-add`` used a
|
||||
single ``bitmap``, the new ``block-export-add`` uses a list of ``bitmaps``.
|
||||
|
||||
``query-qmp-schema`` return value member ``values`` (since 6.2)
|
||||
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
Member ``values`` in return value elements with meta-type ``enum`` is
|
||||
deprecated. Use ``members`` instead.
|
||||
|
||||
System accelerators
|
||||
-------------------
|
||||
|
||||
|
|
|
@ -200,7 +200,9 @@ Syntax::
|
|||
'*if': COND,
|
||||
'*features': FEATURES }
|
||||
ENUM-VALUE = STRING
|
||||
| { 'name': STRING, '*if': COND }
|
||||
| { 'name': STRING,
|
||||
'*if': COND,
|
||||
'*features': FEATURES }
|
||||
|
||||
Member 'enum' names the enum type.
|
||||
|
||||
|
@ -706,8 +708,10 @@ QEMU shows a certain behaviour.
|
|||
Special features
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
Feature "deprecated" marks a command, event, or struct member as
|
||||
deprecated. It is not supported elsewhere so far.
|
||||
Feature "deprecated" marks a command, event, enum value, or struct
|
||||
member as deprecated. It is not supported elsewhere so far.
|
||||
Interfaces so marked may be withdrawn in future releases in accordance
|
||||
with QEMU's deprecation policy.
|
||||
|
||||
|
||||
Naming rules and reserved names
|
||||
|
@ -1157,7 +1161,8 @@ and "variants".
|
|||
|
||||
"members" is a JSON array describing the object's common members, if
|
||||
any. Each element is a JSON object with members "name" (the member's
|
||||
name), "type" (the name of its type), and optionally "default". The
|
||||
name), "type" (the name of its type), "features" (a JSON array of
|
||||
feature strings), and "default". The latter two are optional. The
|
||||
member is optional if "default" is present. Currently, "default" can
|
||||
only have value null. Other values are reserved for future
|
||||
extensions. The "members" array is in no particular order; clients
|
||||
|
@ -1231,14 +1236,22 @@ Example: the SchemaInfo for ['str'] ::
|
|||
"element-type": "str" }
|
||||
|
||||
The SchemaInfo for an enumeration type has meta-type "enum" and
|
||||
variant member "values". The values are listed in no particular
|
||||
order; clients must search the entire enum when learning whether a
|
||||
particular value is supported.
|
||||
variant member "members".
|
||||
|
||||
"members" is a JSON array describing the enumeration values. Each
|
||||
element is a JSON object with member "name" (the member's name), and
|
||||
optionally "features" (a JSON array of feature strings). The
|
||||
"members" array is in no particular order; clients must search the
|
||||
entire array when learning whether a particular value is supported.
|
||||
|
||||
Example: the SchemaInfo for MyEnum from section `Enumeration types`_ ::
|
||||
|
||||
{ "name": "MyEnum", "meta-type": "enum",
|
||||
"values": [ "value1", "value2", "value3" ] }
|
||||
"members": [
|
||||
{ "name": "value1" },
|
||||
{ "name": "value2" },
|
||||
{ "name": "value3" }
|
||||
] }
|
||||
|
||||
The SchemaInfo for a built-in type has the same name as the type in
|
||||
the QAPI schema (see section `Built-in Types`_), with one exception
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#ifndef QOBJECT_INPUT_VISITOR_H
|
||||
#define QOBJECT_INPUT_VISITOR_H
|
||||
|
||||
#include "qapi/qapi-types-compat.h"
|
||||
#include "qapi/visitor.h"
|
||||
|
||||
typedef struct QObjectInputVisitor QObjectInputVisitor;
|
||||
|
@ -59,9 +58,6 @@ typedef struct QObjectInputVisitor QObjectInputVisitor;
|
|||
*/
|
||||
Visitor *qobject_input_visitor_new(QObject *obj);
|
||||
|
||||
void qobject_input_visitor_set_policy(Visitor *v,
|
||||
CompatPolicyInput deprecated);
|
||||
|
||||
/*
|
||||
* Create a QObject input visitor for @obj for use with keyval_parse()
|
||||
*
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#define QOBJECT_OUTPUT_VISITOR_H
|
||||
|
||||
#include "qapi/visitor.h"
|
||||
#include "qapi/qapi-types-compat.h"
|
||||
|
||||
typedef struct QObjectOutputVisitor QObjectOutputVisitor;
|
||||
|
||||
|
@ -54,7 +53,4 @@ typedef struct QObjectOutputVisitor QObjectOutputVisitor;
|
|||
*/
|
||||
Visitor *qobject_output_visitor_new(QObject **result);
|
||||
|
||||
void qobject_output_visitor_set_policy(Visitor *v,
|
||||
CompatPolicyOutput deprecated);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,9 +11,13 @@
|
|||
#ifndef QAPI_UTIL_H
|
||||
#define QAPI_UTIL_H
|
||||
|
||||
/* QEnumLookup flags */
|
||||
#define QAPI_ENUM_DEPRECATED 1
|
||||
|
||||
typedef struct QEnumLookup {
|
||||
const char *const *array;
|
||||
int size;
|
||||
const unsigned char *const flags;
|
||||
const int size;
|
||||
} QEnumLookup;
|
||||
|
||||
const char *qapi_enum_lookup(const QEnumLookup *lookup, int val);
|
||||
|
|
|
@ -122,6 +122,9 @@ struct Visitor
|
|||
/* Must be set */
|
||||
VisitorType type;
|
||||
|
||||
/* Optional */
|
||||
struct CompatPolicy compat_policy;
|
||||
|
||||
/* Must be set for output visitors, optional otherwise. */
|
||||
void (*complete)(Visitor *v, void *opaque);
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define QAPI_VISITOR_H
|
||||
|
||||
#include "qapi/qapi-builtin-types.h"
|
||||
#include "qapi/qapi-types-compat.h"
|
||||
|
||||
/*
|
||||
* The QAPI schema defines both a set of C data types, and a QMP wire
|
||||
|
@ -477,6 +478,14 @@ bool visit_deprecated_accept(Visitor *v, const char *name, Error **errp);
|
|||
*/
|
||||
bool visit_deprecated(Visitor *v, const char *name);
|
||||
|
||||
/*
|
||||
* Set policy for handling deprecated management interfaces.
|
||||
*
|
||||
* Intended use: call visit_set_policy(v, &compat_policy) when
|
||||
* visiting management interface input or output.
|
||||
*/
|
||||
void visit_set_policy(Visitor *v, CompatPolicy *policy);
|
||||
|
||||
/*
|
||||
* Visit an enum value.
|
||||
*
|
||||
|
|
|
@ -42,6 +42,9 @@
|
|||
# with feature 'deprecated'. We may want to extend it to cover
|
||||
# semantic aspects, CLI, and experimental features.
|
||||
#
|
||||
# Limitation: deprecated-output policy @hide is not implemented for
|
||||
# enumeration values. They behave the same as with policy @accept.
|
||||
#
|
||||
# @deprecated-input: how to handle deprecated input (default 'accept')
|
||||
# @deprecated-output: how to handle deprecated output (default 'accept')
|
||||
#
|
||||
|
|
|
@ -142,14 +142,38 @@
|
|||
#
|
||||
# Additional SchemaInfo members for meta-type 'enum'.
|
||||
#
|
||||
# @values: the enumeration type's values, in no particular order.
|
||||
# @members: the enum type's members, in no particular order
|
||||
# (since 6.2).
|
||||
#
|
||||
# @values: the enumeration type's member names, in no particular order.
|
||||
# Redundant with @members. Just for backward compatibility.
|
||||
#
|
||||
# Features:
|
||||
# @deprecated: Member @values is deprecated. Use @members instead.
|
||||
#
|
||||
# Values of this type are JSON string on the wire.
|
||||
#
|
||||
# Since: 2.5
|
||||
##
|
||||
{ 'struct': 'SchemaInfoEnum',
|
||||
'data': { 'values': ['str'] } }
|
||||
'data': { 'members': [ 'SchemaInfoEnumMember' ],
|
||||
'values': { 'type': [ 'str' ],
|
||||
'features': [ 'deprecated' ] } } }
|
||||
|
||||
##
|
||||
# @SchemaInfoEnumMember:
|
||||
#
|
||||
# An object member.
|
||||
#
|
||||
# @name: the member's name, as defined in the QAPI schema.
|
||||
#
|
||||
# @features: names of features associated with the member, in no
|
||||
# particular order.
|
||||
#
|
||||
# Since: 6.2
|
||||
##
|
||||
{ 'struct': 'SchemaInfoEnumMember',
|
||||
'data': { 'name': 'str', '*features': [ 'str' ] } }
|
||||
|
||||
##
|
||||
# @SchemaInfoArray:
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
#include "qapi/visitor-impl.h"
|
||||
#include "trace.h"
|
||||
|
||||
/* Zero-initialization must result in default policy */
|
||||
QEMU_BUILD_BUG_ON(COMPAT_POLICY_INPUT_ACCEPT || COMPAT_POLICY_OUTPUT_ACCEPT);
|
||||
|
||||
|
||||
void visit_complete(Visitor *v, void *opaque)
|
||||
{
|
||||
assert(v->type != VISITOR_OUTPUT || v->complete);
|
||||
|
@ -153,6 +157,11 @@ bool visit_deprecated(Visitor *v, const char *name)
|
|||
return true;
|
||||
}
|
||||
|
||||
void visit_set_policy(Visitor *v, CompatPolicy *policy)
|
||||
{
|
||||
v->compat_policy = *policy;
|
||||
}
|
||||
|
||||
bool visit_is_input(Visitor *v)
|
||||
{
|
||||
return v->type == VISITOR_INPUT;
|
||||
|
@ -384,7 +393,7 @@ static bool input_type_enum(Visitor *v, const char *name, int *obj,
|
|||
const QEnumLookup *lookup, Error **errp)
|
||||
{
|
||||
int64_t value;
|
||||
char *enum_str;
|
||||
g_autofree char *enum_str = NULL;
|
||||
|
||||
if (!visit_type_str(v, name, &enum_str, errp)) {
|
||||
return false;
|
||||
|
@ -392,12 +401,25 @@ static bool input_type_enum(Visitor *v, const char *name, int *obj,
|
|||
|
||||
value = qapi_enum_parse(lookup, enum_str, -1, NULL);
|
||||
if (value < 0) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER, enum_str);
|
||||
g_free(enum_str);
|
||||
error_setg(errp, "Parameter '%s' does not accept value '%s'",
|
||||
name ? name : "null", enum_str);
|
||||
return false;
|
||||
}
|
||||
|
||||
g_free(enum_str);
|
||||
if (lookup->flags && (lookup->flags[value] & QAPI_ENUM_DEPRECATED)) {
|
||||
switch (v->compat_policy.deprecated_input) {
|
||||
case COMPAT_POLICY_INPUT_ACCEPT:
|
||||
break;
|
||||
case COMPAT_POLICY_INPUT_REJECT:
|
||||
error_setg(errp, "Deprecated value '%s' disabled by policy",
|
||||
enum_str);
|
||||
return false;
|
||||
case COMPAT_POLICY_INPUT_CRASH:
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
*obj = value;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ Visitor *qobject_input_visitor_new_qmp(QObject *obj)
|
|||
{
|
||||
Visitor *v = qobject_input_visitor_new(obj);
|
||||
|
||||
qobject_input_visitor_set_policy(v, compat_policy.deprecated_input);
|
||||
visit_set_policy(v, &compat_policy);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ Visitor *qobject_output_visitor_new_qmp(QObject **result)
|
|||
{
|
||||
Visitor *v = qobject_output_visitor_new(result);
|
||||
|
||||
qobject_output_visitor_set_policy(v, compat_policy.deprecated_output);
|
||||
visit_set_policy(v, &compat_policy);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
#include "qemu/osdep.h"
|
||||
#include <math.h>
|
||||
#include "qapi/compat-policy.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "qapi/visitor-impl.h"
|
||||
|
@ -44,7 +43,6 @@ typedef struct StackObject {
|
|||
|
||||
struct QObjectInputVisitor {
|
||||
Visitor visitor;
|
||||
CompatPolicyInput deprecated_policy;
|
||||
|
||||
/* Root of visit at visitor creation. */
|
||||
QObject *root;
|
||||
|
@ -667,9 +665,7 @@ static void qobject_input_optional(Visitor *v, const char *name, bool *present)
|
|||
static bool qobject_input_deprecated_accept(Visitor *v, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
|
||||
switch (qiv->deprecated_policy) {
|
||||
switch (v->compat_policy.deprecated_input) {
|
||||
case COMPAT_POLICY_INPUT_ACCEPT:
|
||||
return true;
|
||||
case COMPAT_POLICY_INPUT_REJECT:
|
||||
|
@ -739,14 +735,6 @@ Visitor *qobject_input_visitor_new(QObject *obj)
|
|||
return &v->visitor;
|
||||
}
|
||||
|
||||
void qobject_input_visitor_set_policy(Visitor *v,
|
||||
CompatPolicyInput deprecated)
|
||||
{
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
|
||||
qiv->deprecated_policy = deprecated;
|
||||
}
|
||||
|
||||
Visitor *qobject_input_visitor_new_keyval(QObject *obj)
|
||||
{
|
||||
QObjectInputVisitor *v = qobject_input_visitor_base_new(obj);
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/compat-policy.h"
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
#include "qapi/visitor-impl.h"
|
||||
#include "qemu/queue.h"
|
||||
|
@ -32,7 +31,6 @@ typedef struct QStackEntry {
|
|||
|
||||
struct QObjectOutputVisitor {
|
||||
Visitor visitor;
|
||||
CompatPolicyOutput deprecated_policy;
|
||||
|
||||
QSLIST_HEAD(, QStackEntry) stack; /* Stack of unfinished containers */
|
||||
QObject *root; /* Root of the output visit */
|
||||
|
@ -212,9 +210,7 @@ static bool qobject_output_type_null(Visitor *v, const char *name,
|
|||
|
||||
static bool qobject_output_deprecated(Visitor *v, const char *name)
|
||||
{
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
|
||||
return qov->deprecated_policy != COMPAT_POLICY_OUTPUT_HIDE;
|
||||
return v->compat_policy.deprecated_output != COMPAT_POLICY_OUTPUT_HIDE;
|
||||
}
|
||||
|
||||
/* Finish building, and return the root object.
|
||||
|
@ -275,11 +271,3 @@ Visitor *qobject_output_visitor_new(QObject **result)
|
|||
|
||||
return &v->visitor;
|
||||
}
|
||||
|
||||
void qobject_output_visitor_set_policy(Visitor *v,
|
||||
CompatPolicyOutput deprecated)
|
||||
{
|
||||
QObjectOutputVisitor *qov = to_qov(v);
|
||||
|
||||
qov->deprecated_policy = deprecated;
|
||||
}
|
||||
|
|
|
@ -472,7 +472,7 @@ def check_enum(expr: _JSONObject, info: QAPISourceInfo) -> None:
|
|||
for m in members]
|
||||
for member in members:
|
||||
source = "'data' member"
|
||||
check_keys(member, info, source, ['name'], ['if'])
|
||||
check_keys(member, info, source, ['name'], ['if', 'features'])
|
||||
member_name = member['name']
|
||||
check_name_is_str(member_name, info, source)
|
||||
source = "%s '%s'" % (source, member_name)
|
||||
|
@ -483,6 +483,7 @@ def check_enum(expr: _JSONObject, info: QAPISourceInfo) -> None:
|
|||
permit_upper=permissive,
|
||||
permit_underscore=permissive)
|
||||
check_if(member, info, source)
|
||||
check_features(member.get('features'), info)
|
||||
|
||||
|
||||
def check_struct(expr: _JSONObject, info: QAPISourceInfo) -> None:
|
||||
|
|
|
@ -68,6 +68,7 @@ JSONValue = Union[_Value, 'Annotated[_Value]']
|
|||
# TypedDict constructs, so they are broadly typed here as simple
|
||||
# Python Dicts.
|
||||
SchemaInfo = Dict[str, object]
|
||||
SchemaInfoEnumMember = Dict[str, object]
|
||||
SchemaInfoObject = Dict[str, object]
|
||||
SchemaInfoObjectVariant = Dict[str, object]
|
||||
SchemaInfoObjectMember = Dict[str, object]
|
||||
|
@ -274,7 +275,16 @@ const QLitObject %(c_name)s = %(c_string)s;
|
|||
obj['features'] = self._gen_features(features)
|
||||
self._trees.append(Annotated(obj, ifcond, comment))
|
||||
|
||||
def _gen_member(self, member: QAPISchemaObjectTypeMember
|
||||
def _gen_enum_member(self, member: QAPISchemaEnumMember
|
||||
) -> Annotated[SchemaInfoEnumMember]:
|
||||
obj: SchemaInfoEnumMember = {
|
||||
'name': member.name,
|
||||
}
|
||||
if member.features:
|
||||
obj['features'] = self._gen_features(member.features)
|
||||
return Annotated(obj, member.ifcond)
|
||||
|
||||
def _gen_object_member(self, member: QAPISchemaObjectTypeMember
|
||||
) -> Annotated[SchemaInfoObjectMember]:
|
||||
obj: SchemaInfoObjectMember = {
|
||||
'name': member.name,
|
||||
|
@ -305,7 +315,8 @@ const QLitObject %(c_name)s = %(c_string)s;
|
|||
prefix: Optional[str]) -> None:
|
||||
self._gen_tree(
|
||||
name, 'enum',
|
||||
{'values': [Annotated(m.name, m.ifcond) for m in members]},
|
||||
{'members': [self._gen_enum_member(m) for m in members],
|
||||
'values': [Annotated(m.name, m.ifcond) for m in members]},
|
||||
ifcond, features
|
||||
)
|
||||
|
||||
|
@ -322,7 +333,7 @@ const QLitObject %(c_name)s = %(c_string)s;
|
|||
members: List[QAPISchemaObjectTypeMember],
|
||||
variants: Optional[QAPISchemaVariants]) -> None:
|
||||
obj: SchemaInfoObject = {
|
||||
'members': [self._gen_member(m) for m in members]
|
||||
'members': [self._gen_object_member(m) for m in members]
|
||||
}
|
||||
if variants:
|
||||
obj['tag'] = variants.tag_member.name
|
||||
|
|
|
@ -708,6 +708,19 @@ class QAPISchemaMember:
|
|||
class QAPISchemaEnumMember(QAPISchemaMember):
|
||||
role = 'value'
|
||||
|
||||
def __init__(self, name, info, ifcond=None, features=None):
|
||||
super().__init__(name, info, ifcond)
|
||||
for f in features or []:
|
||||
assert isinstance(f, QAPISchemaFeature)
|
||||
f.set_defined_in(name)
|
||||
self.features = features or []
|
||||
|
||||
def connect_doc(self, doc):
|
||||
super().connect_doc(doc)
|
||||
if doc:
|
||||
for f in self.features:
|
||||
doc.connect_feature(f)
|
||||
|
||||
|
||||
class QAPISchemaFeature(QAPISchemaMember):
|
||||
role = 'feature'
|
||||
|
@ -980,9 +993,14 @@ class QAPISchema:
|
|||
QAPISchemaIfCond(f.get('if')))
|
||||
for f in features]
|
||||
|
||||
def _make_enum_member(self, name, ifcond, features, info):
|
||||
return QAPISchemaEnumMember(name, info,
|
||||
QAPISchemaIfCond(ifcond),
|
||||
self._make_features(features, info))
|
||||
|
||||
def _make_enum_members(self, values, info):
|
||||
return [QAPISchemaEnumMember(v['name'], info,
|
||||
QAPISchemaIfCond(v.get('if')))
|
||||
return [self._make_enum_member(v['name'], v.get('if'),
|
||||
v.get('features'), info)
|
||||
for v in values]
|
||||
|
||||
def _make_array_type(self, element_type, info):
|
||||
|
|
|
@ -38,6 +38,8 @@ objects_seen = set()
|
|||
def gen_enum_lookup(name: str,
|
||||
members: List[QAPISchemaEnumMember],
|
||||
prefix: Optional[str] = None) -> str:
|
||||
max_index = c_enum_const(name, '_MAX', prefix)
|
||||
flags = ''
|
||||
ret = mcgen('''
|
||||
|
||||
const QEnumLookup %(c_name)s_lookup = {
|
||||
|
@ -52,13 +54,26 @@ const QEnumLookup %(c_name)s_lookup = {
|
|||
''',
|
||||
index=index, name=memb.name)
|
||||
ret += memb.ifcond.gen_endif()
|
||||
if 'deprecated' in (f.name for f in memb.features):
|
||||
flags += mcgen('''
|
||||
[%(index)s] = QAPI_ENUM_DEPRECATED,
|
||||
''',
|
||||
index=index)
|
||||
|
||||
if flags:
|
||||
ret += mcgen('''
|
||||
},
|
||||
.flags = (const unsigned char[%(max_index)s]) {
|
||||
''',
|
||||
max_index=max_index)
|
||||
ret += flags
|
||||
|
||||
ret += mcgen('''
|
||||
},
|
||||
.size = %(max_index)s
|
||||
};
|
||||
''',
|
||||
max_index=c_enum_const(name, '_MAX', prefix))
|
||||
max_index=max_index)
|
||||
return ret
|
||||
|
||||
|
||||
|
|
|
@ -58,11 +58,14 @@
|
|||
#
|
||||
# Features:
|
||||
# @enum-feat: Also _one_ {and only}
|
||||
# @enum-member-feat: a member feature
|
||||
#
|
||||
# @two is undocumented
|
||||
##
|
||||
{ 'enum': 'Enum',
|
||||
'data': [ { 'name': 'one', 'if': 'IFONE' }, 'two' ],
|
||||
'data': [ { 'name': 'one', 'if': 'IFONE',
|
||||
'features': [ 'enum-member-feat' ] },
|
||||
'two' ],
|
||||
'features': [ 'enum-feat' ],
|
||||
'if': 'IFCOND' }
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ module doc-good.json
|
|||
enum Enum
|
||||
member one
|
||||
if IFONE
|
||||
feature enum-member-feat
|
||||
member two
|
||||
if IFCOND
|
||||
feature enum-feat
|
||||
|
@ -108,6 +109,8 @@ The _one_ {and only}
|
|||
|
||||
feature=enum-feat
|
||||
Also _one_ {and only}
|
||||
feature=enum-member-feat
|
||||
a member feature
|
||||
section=None
|
||||
@two is undocumented
|
||||
doc symbol=Base
|
||||
|
|
|
@ -56,6 +56,9 @@ Features
|
|||
"enum-feat"
|
||||
Also _one_ {and only}
|
||||
|
||||
"enum-member-feat"
|
||||
a member feature
|
||||
|
||||
"two" is undocumented
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
enum-dict-member-unknown.json: In enum 'MyEnum':
|
||||
enum-dict-member-unknown.json:2: 'data' member has unknown key 'bad-key'
|
||||
Valid keys are 'if', 'name'.
|
||||
Valid keys are 'features', 'if', 'name'.
|
||||
|
|
|
@ -301,7 +301,8 @@
|
|||
'TEST_IF_COND_2'] } } ] }
|
||||
|
||||
{ 'enum': 'FeatureEnum1',
|
||||
'data': [ 'eins', 'zwei', 'drei' ],
|
||||
'data': [ 'eins', 'zwei',
|
||||
{ 'name': 'drei', 'features': [ 'deprecated' ] } ],
|
||||
'features': [ 'feature1' ] }
|
||||
|
||||
{ 'union': 'FeatureUnion1',
|
||||
|
|
|
@ -341,6 +341,7 @@ enum FeatureEnum1
|
|||
member eins
|
||||
member zwei
|
||||
member drei
|
||||
feature deprecated
|
||||
feature feature1
|
||||
object q_obj_FeatureUnion1-base
|
||||
member tag: FeatureEnum1 optional=False
|
||||
|
|
|
@ -37,6 +37,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
|
|||
for m in members:
|
||||
print(' member %s' % m.name)
|
||||
self._print_if(m.ifcond, indent=8)
|
||||
self._print_features(m.features, indent=8)
|
||||
self._print_if(ifcond)
|
||||
self._print_features(features)
|
||||
|
||||
|
|
|
@ -174,11 +174,11 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off comp
|
|||
|
||||
qemu-img create -f qcow2 -o compat=0.42 TEST_DIR/t.qcow2 64M
|
||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.42 lazy_refcounts=off refcount_bits=16
|
||||
qemu-img: TEST_DIR/t.qcow2: Invalid parameter '0.42'
|
||||
qemu-img: TEST_DIR/t.qcow2: Parameter 'version' does not accept value '0.42'
|
||||
|
||||
qemu-img create -f qcow2 -o compat=foobar TEST_DIR/t.qcow2 64M
|
||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=foobar lazy_refcounts=off refcount_bits=16
|
||||
qemu-img: TEST_DIR/t.qcow2: Invalid parameter 'foobar'
|
||||
qemu-img: TEST_DIR/t.qcow2: Parameter 'version' does not accept value 'foobar'
|
||||
|
||||
== Check preallocation option ==
|
||||
|
||||
|
@ -190,7 +190,7 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off prea
|
|||
|
||||
qemu-img create -f qcow2 -o preallocation=1234 TEST_DIR/t.qcow2 64M
|
||||
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=1234 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
|
||||
qemu-img: TEST_DIR/t.qcow2: Invalid parameter '1234'
|
||||
qemu-img: TEST_DIR/t.qcow2: Parameter 'preallocation' does not accept value '1234'
|
||||
|
||||
== Check encryption option ==
|
||||
|
||||
|
|
|
@ -192,7 +192,7 @@ Job failed: Could not resize image: Failed to grow the L1 table: File too large
|
|||
|
||||
=== Invalid version ===
|
||||
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 67108864, "version": "v1"}}}
|
||||
{"error": {"class": "GenericError", "desc": "Invalid parameter 'v1'"}}
|
||||
{"error": {"class": "GenericError", "desc": "Parameter 'version' does not accept value 'v1'"}}
|
||||
|
||||
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "lazy-refcounts": true, "size": 67108864, "version": "v2"}}}
|
||||
{"return": {}}
|
||||
|
|
|
@ -116,13 +116,13 @@ Job failed: Cannot find device='this doesn't exist' nor node-name='this doesn't
|
|||
== Invalid adapter types ==
|
||||
|
||||
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "foo", "driver": "vmdk", "file": "node0", "size": 33554432}}}
|
||||
{"error": {"class": "GenericError", "desc": "Invalid parameter 'foo'"}}
|
||||
{"error": {"class": "GenericError", "desc": "Parameter 'adapter-type' does not accept value 'foo'"}}
|
||||
|
||||
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "IDE", "driver": "vmdk", "file": "node0", "size": 33554432}}}
|
||||
{"error": {"class": "GenericError", "desc": "Invalid parameter 'IDE'"}}
|
||||
{"error": {"class": "GenericError", "desc": "Parameter 'adapter-type' does not accept value 'IDE'"}}
|
||||
|
||||
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "legacyesx", "driver": "vmdk", "file": "node0", "size": 33554432}}}
|
||||
{"error": {"class": "GenericError", "desc": "Invalid parameter 'legacyesx'"}}
|
||||
{"error": {"class": "GenericError", "desc": "Parameter 'adapter-type' does not accept value 'legacyesx'"}}
|
||||
|
||||
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": 1, "driver": "vmdk", "file": "node0", "size": 33554432}}}
|
||||
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'options.adapter-type', expected: string"}}
|
||||
|
|
|
@ -149,7 +149,7 @@ class TestBlockdevReopen(iotests.QMPTestCase):
|
|||
self.reopen(opts, {'node-name': ''}, "Failed to find node with node-name=''")
|
||||
self.reopen(opts, {'node-name': None}, "Invalid parameter type for 'options[0].node-name', expected: string")
|
||||
self.reopen(opts, {'driver': 'raw'}, "Cannot change the option 'driver'")
|
||||
self.reopen(opts, {'driver': ''}, "Invalid parameter ''")
|
||||
self.reopen(opts, {'driver': ''}, "Parameter 'driver' does not accept value ''")
|
||||
self.reopen(opts, {'driver': None}, "Invalid parameter type for 'options[0].driver', expected: string")
|
||||
self.reopen(opts, {'file': 'not-found'}, "Cannot find device='' nor node-name='not-found'")
|
||||
self.reopen(opts, {'file': ''}, "Cannot find device='' nor node-name=''")
|
||||
|
|
|
@ -53,7 +53,7 @@ CLUSTER_SIZE=65536
|
|||
|
||||
# Check if we can run this test.
|
||||
output=$(_make_test_img -o 'compression_type=zstd' 64M; _cleanup_test_img)
|
||||
if echo "$output" | grep -q "Invalid parameter 'zstd'"; then
|
||||
if echo "$output" | grep -q "Parameter 'compression-type' does not accept value 'zstd'"; then
|
||||
_notrun "ZSTD is disabled"
|
||||
fi
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ rmdir "$EXT_MP" 2>/dev/null
|
|||
rm -f "$EXT_MP"
|
||||
output=$(fuse_export_add 'export-err' "'mountpoint': '$EXT_MP'" error)
|
||||
|
||||
if echo "$output" | grep -q "Invalid parameter 'fuse'"; then
|
||||
if echo "$output" | grep -q "Parameter 'type' does not accept value 'fuse'"; then
|
||||
_notrun 'No FUSE support'
|
||||
fi
|
||||
|
||||
|
|
|
@ -488,7 +488,7 @@ static void test_dummy_badenum(void)
|
|||
g_assert(dobj == NULL);
|
||||
g_assert(err != NULL);
|
||||
g_assert_cmpstr(error_get_pretty(err), ==,
|
||||
"Invalid parameter 'yeti'");
|
||||
"Parameter 'av' does not accept value 'yeti'");
|
||||
|
||||
g_assert(object_resolve_path_component(parent, "dummy0")
|
||||
== NULL);
|
||||
|
|
Loading…
Reference in a new issue