337
qtest_quit(qts);
338
}
339
340
+static void test_qmp_monitor_add_remove(void)
341
+{
342
+ QTestState *qts;
343
+ QDict *resp;
344
+
345
+ qts = qtest_init(common_args);
346
+
347
+ /* Create a null chardev for the dynamic monitor */
348
+ resp = qtest_qmp(qts,
349
+ "{'execute': 'chardev-add',"
350
+ " 'arguments': {'id': 'monitor-chardev',"
351
+ " 'backend': {'type': 'null',"
352
+ " 'data': {}}}}");
353
+ g_assert(qdict_haskey(resp, "return"));
354
+ qobject_unref(resp);
355
+
356
+ /* Add a dynamic monitor */
357
+ resp = qtest_qmp(qts,
358
+ "{'execute': 'object-add',"
359
+ " 'arguments': {'qom-type': 'monitor-qmp',"
360
+ " 'id': 'dyn-mon',"
361
+ " 'chardev': 'monitor-chardev'}}");
362
+ g_assert(qdict_haskey(resp, "return"));
363
+ qobject_unref(resp);
364
+
365
+ /* Remove the dynamic monitor */
366
+ resp = qtest_qmp(qts,
367
+ "{'execute': 'object-del',"
368
+ " 'arguments': {'id': 'dyn-mon'}}");
369
+ g_assert(qdict_haskey(resp, "return"));
370
+ qobject_unref(resp);
371
+
372
+ /* Add again after remove -- same id and chardev should work */
373
+ resp = qtest_qmp(qts,
374
+ "{'execute': 'object-add',"
375
+ " 'arguments': {'qom-type': 'monitor-qmp',"
376
+ " 'id': 'dyn-mon',"
377
+ " 'chardev': 'monitor-chardev'}}");
378
+ g_assert(qdict_haskey(resp, "return"));
379
+ qobject_unref(resp);
380
+
381
+ /* Clean up */
382
+ resp = qtest_qmp(qts,
383
+ "{'execute': 'object-del',"
384
+ " 'arguments': {'id': 'dyn-mon'}}");
385
+ g_assert(qdict_haskey(resp, "return"));
386
+ qobject_unref(resp);
387
+
388
+ resp = qtest_qmp(qts,
389
+ "{'execute': 'chardev-remove',"
390
+ " 'arguments': {'id': 'monitor-chardev'}}");
391
+ g_assert(qdict_haskey(resp, "return"));
392
+ qobject_unref(resp);
393
+
394
+ qtest_quit(qts);
395
+}
396
+
397
+static void test_qmp_monitor_error_paths(void)
398
+{
399
+ QTestState *qts;
400
+ QDict *resp;
401
+
402
+ qts = qtest_init(common_args);
403
+
404
+ /* Error: chardev does not exist */
405
+ resp = qtest_qmp(qts,
406
+ "{'execute': 'object-add',"
407
+ " 'arguments': {'qom-type': 'monitor-qmp',"
408
+ " 'id': 'bad-mon',"
409
+ " 'chardev': 'nonexistent'}}");
410
+ qmp_expect_error_and_unref(resp, "GenericError");
411
+
412
+ qtest_quit(qts);
413
+}
414
+
415
+static void test_qmp_monitor_chardev_in_use(void)
416
+{
417
+ QTestState *qts;
418
+ QDict *resp;
419
+
420
+ qts = qtest_init(common_args);
421
+
422
+ /* Create a null chardev */
423
+ resp = qtest_qmp(qts,
424
+ "{'execute': 'chardev-add',"
425
+ " 'arguments': {'id': 'shared-chr',"
426
+ " 'backend': {'type': 'null',"
427
+ " 'data': {}}}}");
428
+ g_assert(qdict_haskey(resp, "return"));
429
+ qobject_unref(resp);
430
+
431
+ /* Attach first monitor */
432
+ resp = qtest_qmp(qts,
433
+ "{'execute': 'object-add',"
434
+ " 'arguments': {'qom-type': 'monitor-qmp',"
435
+ " 'id': 'mon-1',"
436
+ " 'chardev': 'shared-chr'}}");
437
+ g_assert(qdict_haskey(resp, "return"));
438
+ qobject_unref(resp);
439
+
440
+ /* Error: second monitor on the same chardev */
441
+ resp = qtest_qmp(qts,
442
+ "{'execute': 'object-add',"
443
+ " 'arguments': {'qom-type': 'monitor-qmp',"
444
+ " 'id': 'mon-2',"
445
+ " 'chardev': 'shared-chr'}}");
446
+ qmp_expect_error_and_unref(resp, "GenericError");
447
+
448
+ /* Clean up */
449
+ resp = qtest_qmp(qts,
450
+ "{'execute': 'object-del',"
451
+ " 'arguments': {'id': 'mon-1'}}");
452
+ g_assert(qdict_haskey(resp, "return"));
453
+ qobject_unref(resp);
454
+
455
+ resp = qtest_qmp(qts,
456
+ "{'execute': 'chardev-remove',"
457
+ " 'arguments': {'id': 'shared-chr'}}");
458
+ g_assert(qdict_haskey(resp, "return"));
459
+ qobject_unref(resp);
460
+
461
+ qtest_quit(qts);
462
+}
463
+
464
+static void test_qmp_monitor_remove_cli(void)
465
+{
466
+ QTestState *qts;
467
+ QDict *resp;
468
+
469
+ /* Launch with a named CLI monitor on a null chardev */
470
+ qts = qtest_initf("%s -chardev null,id=cli-chr"
471
+ " -object monitor-qmp,id=cli-mon,chardev=cli-chr",
472
+ common_args);
473
+
474
+ /* CLI-created QMP monitors can be removed */
475
+ resp = qtest_qmp(qts,
476
+ "{'execute': 'object-del',"
477
+ " 'arguments': {'id': 'cli-mon'}}");
478
+ g_assert(qdict_haskey(resp, "return"));
479
+ qobject_unref(resp);
480
+
481
+ resp = qtest_qmp(qts,
482
+ "{'execute': 'chardev-remove',"
483
+ " 'arguments': {'id': 'cli-chr'}}");
484
+ g_assert(qdict_haskey(resp, "return"));
485
+ qobject_unref(resp);
486
+
487
+ qtest_quit(qts);
488
+}
489
+
490
+static void test_qmp_monitor_remove_hmp(void)
491
+{
492
+ QTestState *qts;
493
+ QDict *resp;
494
+
495
+ qts = qtest_initf("%s -chardev null,id=hmp-chr"
496
+ " -object monitor-hmp,id=hmp-mon,chardev=hmp-chr",
497
+ common_args);
498
+
499
+ /* Error: object_del must reject HMP monitors */
500
+ resp = qtest_qmp(qts,
501
+ "{'execute': 'object-del',"
502
+ " 'arguments': {'id': 'hmp-mon'}}");
503
+ qmp_expect_error_and_unref(resp, "GenericError");
504
+
505
+ qtest_quit(qts);
506
+}
507
+
508
int main(int argc, char *argv[])
509
{
510
g_test_init(&argc, &argv, NULL);
516
#endif
517
qtest_add_func("qmp/preconfig", test_qmp_preconfig);
518
qtest_add_func("qmp/missing-any-arg", test_qmp_missing_any_arg);
519
+ qtest_add_func("qmp/monitor-add-remove", test_qmp_monitor_add_remove);
520
+ qtest_add_func("qmp/monitor-error-paths", test_qmp_monitor_error_paths);
521
+ qtest_add_func("qmp/monitor-chardev-in-use",
522
+ test_qmp_monitor_chardev_in_use);
523
+ qtest_add_func("qmp/monitor-remove-cli", test_qmp_monitor_remove_cli);
524
+ qtest_add_func("qmp/monitor-remove-hmp", test_qmp_monitor_remove_hmp);
525
526
return g_test_run();
527
}