qemu/tests/qapi-schema/qapi-schema-test.out
Markus Armbruster 39a1815816 qapi: New QMP command query-qmp-schema for QMP introspection
qapi/introspect.json defines the introspection schema.  It's designed
for QMP introspection, but should do for similar uses, such as QGA.

The introspection schema does not reflect all the rules and
restrictions that apply to QAPI schemata.  A valid QAPI schema has an
introspection value conforming to the introspection schema, but the
converse is not true.

Introspection lowers away a number of schema details, and makes
implicit things explicit:

* The built-in types are declared with their JSON type.

  All integer types are mapped to 'int', because how many bits we use
  internally is an implementation detail.  It could be pressed into
  external interface service as very approximate range information,
  but that's a bad idea.  If we need range information, we better do
  it properly.

* Implicit type definitions are made explicit, and given
  auto-generated names:

  - Array types, named by appending "List" to the name of their
    element type, like in generated C.

  - The enumeration types implicitly defined by simple union types,
    named by appending "Kind" to the name of their simple union type,
    like in generated C.

  - Types that don't occur in generated C.  Their names start with ':'
    so they don't clash with the user's names.

* All type references are by name.

* The struct and union types are generalized into an object type.

* Base types are flattened.

* Commands take a single argument and return a single result.

  Dictionary argument or list result is an implicit type definition.

  The empty object type is used when a command takes no arguments or
  produces no results.

  The argument is always of object type, but the introspection schema
  doesn't reflect that.

  The 'gen': false directive is omitted as implementation detail.

  The 'success-response' directive is omitted as well for now, even
  though it's not an implementation detail, because it's not used by
  QMP.

* Events carry a single data value.

  Implicit type definition and empty object type use, just like for
  commands.

  The value is of object type, but the introspection schema doesn't
  reflect that.

* Types not used by commands or events are omitted.

  Indirect use counts as use.

* Optional members have a default, which can only be null right now

  Instead of a mandatory "optional" flag, we have an optional default.
  No default means mandatory, default null means optional without
  default value.  Non-null is available for optional with default
  (possible future extension).

* Clients should *not* look up types by name, because type names are
  not ABI.  Look up the command or event you're interested in, then
  follow the references.

  TODO Should we hide the type names to eliminate the temptation?

New generator scripts/qapi-introspect.py computes an introspection
value for its input, and generates a C variable holding it.

It can generate awfully long lines.  Marked TODO.

A new test-qmp-input-visitor test case feeds its result for both
tests/qapi-schema/qapi-schema-test.json and qapi-schema.json to a
QmpInputVisitor to verify it actually conforms to the schema.

New QMP command query-qmp-schema takes its return value from that
variable.  Its reply is some 85KiBytes for me right now.

If this turns out to be too much, we have a couple of options:

* We can use shorter names in the JSON.  Not the QMP style.

* Optionally return the sub-schema for commands and events given as
  arguments.

  Right now qmp_query_schema() sends the string literal computed by
  qmp-introspect.py.  To compute sub-schema at run time, we'd have to
  duplicate parts of qapi-introspect.py in C.  Unattractive.

* Let clients cache the output of query-qmp-schema.

  It changes only on QEMU upgrades, i.e. rarely.  Provide a command
  query-qmp-schema-hash.  Clients can have a cache indexed by hash,
  and re-query the schema only when they don't have it cached.  Even
  simpler: put the hash in the QMP greeting.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-21 09:56:49 +02:00

170 lines
5.9 KiB
Plaintext

object :empty
object :obj-EVENT_C-arg
member a: int optional=True
member b: UserDefOne optional=True
member c: str optional=False
object :obj-EVENT_D-arg
member a: EventStructOne optional=False
member b: str optional=False
member c: str optional=True
member enum3: EnumOne optional=True
object :obj-__org.qemu_x-command-arg
member a: __org.qemu_x-EnumList optional=False
member b: __org.qemu_x-StructList optional=False
member c: __org.qemu_x-Union2 optional=False
member d: __org.qemu_x-Alt optional=False
object :obj-anyList-wrapper
member data: anyList optional=False
object :obj-boolList-wrapper
member data: boolList optional=False
object :obj-guest-sync-arg
member arg: any optional=False
object :obj-int16List-wrapper
member data: int16List optional=False
object :obj-int32List-wrapper
member data: int32List optional=False
object :obj-int64List-wrapper
member data: int64List optional=False
object :obj-int8List-wrapper
member data: int8List optional=False
object :obj-intList-wrapper
member data: intList optional=False
object :obj-numberList-wrapper
member data: numberList optional=False
object :obj-sizeList-wrapper
member data: sizeList optional=False
object :obj-str-wrapper
member data: str optional=False
object :obj-strList-wrapper
member data: strList optional=False
object :obj-uint16List-wrapper
member data: uint16List optional=False
object :obj-uint32List-wrapper
member data: uint32List optional=False
object :obj-uint64List-wrapper
member data: uint64List optional=False
object :obj-uint8List-wrapper
member data: uint8List optional=False
object :obj-user_def_cmd1-arg
member ud1a: UserDefOne optional=False
object :obj-user_def_cmd2-arg
member ud1a: UserDefOne optional=False
member ud1b: UserDefOne optional=True
object :obj-user_def_cmd3-arg
member a: int optional=False
member b: int optional=True
event EVENT_A None
event EVENT_B None
event EVENT_C :obj-EVENT_C-arg
event EVENT_D :obj-EVENT_D-arg
enum EnumOne ['value1', 'value2', 'value3']
object EventStructOne
member struct1: UserDefOne optional=False
member string: str optional=False
member enum2: EnumOne optional=True
object NestedEnumsOne
member enum1: EnumOne optional=False
member enum2: EnumOne optional=True
member enum3: EnumOne optional=False
member enum4: EnumOne optional=True
enum QEnumTwo ['value1', 'value2']
prefix QENUM_TWO
object UserDefA
member boolean: bool optional=False
alternate UserDefAlternate
case uda: UserDefA
case s: str
case i: int
enum UserDefAlternateKind ['uda', 's', 'i']
object UserDefB
member intb: int optional=False
object UserDefC
member string1: str optional=False
member string2: str optional=False
object UserDefFlatUnion
base UserDefUnionBase
tag enum1
case value1: UserDefA
case value2: UserDefB
case value3: UserDefB
object UserDefFlatUnion2
base UserDefUnionBase
tag enum1
case value1: UserDefC
case value2: UserDefB
case value3: UserDefA
object UserDefNativeListUnion
case integer: :obj-intList-wrapper
case s8: :obj-int8List-wrapper
case s16: :obj-int16List-wrapper
case s32: :obj-int32List-wrapper
case s64: :obj-int64List-wrapper
case u8: :obj-uint8List-wrapper
case u16: :obj-uint16List-wrapper
case u32: :obj-uint32List-wrapper
case u64: :obj-uint64List-wrapper
case number: :obj-numberList-wrapper
case boolean: :obj-boolList-wrapper
case string: :obj-strList-wrapper
case sizes: :obj-sizeList-wrapper
case any: :obj-anyList-wrapper
enum UserDefNativeListUnionKind ['integer', 's8', 's16', 's32', 's64', 'u8', 'u16', 'u32', 'u64', 'number', 'boolean', 'string', 'sizes', 'any']
object UserDefOne
base UserDefZero
member string: str optional=False
member enum1: EnumOne optional=True
object UserDefOptions
member i64: intList optional=True
member u64: uint64List optional=True
member u16: uint16List optional=True
member i64x: int optional=True
member u64x: uint64 optional=True
object UserDefTwo
member string0: str optional=False
member dict1: UserDefTwoDict optional=False
object UserDefTwoDict
member string1: str optional=False
member dict2: UserDefTwoDictDict optional=False
member dict3: UserDefTwoDictDict optional=True
object UserDefTwoDictDict
member userdef: UserDefOne optional=False
member string: str optional=False
object UserDefUnionBase
base UserDefZero
member string: str optional=False
member enum1: EnumOne optional=False
object UserDefZero
member integer: int optional=False
event __ORG.QEMU_X-EVENT __org.qemu_x-Struct
alternate __org.qemu_x-Alt
case __org.qemu_x-branch: str
case b: __org.qemu_x-Base
enum __org.qemu_x-AltKind ['__org.qemu_x-branch', 'b']
object __org.qemu_x-Base
member __org.qemu_x-member1: __org.qemu_x-Enum optional=False
enum __org.qemu_x-Enum ['__org.qemu_x-value']
object __org.qemu_x-Struct
base __org.qemu_x-Base
member __org.qemu_x-member2: str optional=False
object __org.qemu_x-Struct2
member array: __org.qemu_x-Union1List optional=False
object __org.qemu_x-Union1
case __org.qemu_x-branch: :obj-str-wrapper
enum __org.qemu_x-Union1Kind ['__org.qemu_x-branch']
object __org.qemu_x-Union2
base __org.qemu_x-Base
tag __org.qemu_x-member1
case __org.qemu_x-value: __org.qemu_x-Struct2
command __org.qemu_x-command :obj-__org.qemu_x-command-arg -> __org.qemu_x-Union1
gen=True success_response=True
command guest-sync :obj-guest-sync-arg -> any
gen=True success_response=True
command user_def_cmd None -> None
gen=True success_response=True
command user_def_cmd1 :obj-user_def_cmd1-arg -> None
gen=True success_response=True
command user_def_cmd2 :obj-user_def_cmd2-arg -> UserDefTwo
gen=True success_response=True
command user_def_cmd3 :obj-user_def_cmd3-arg -> int
gen=True success_response=True