@@ -9,6 +9,19 @@ let initialize () =
99 let cons = Connections. create () in
1010 (store, doms, cons)
1111
12+ let initialize_main_loop () =
13+ Domains. xenstored_port := " /tmp/port" ;
14+ let fd =
15+ Unix. openfile ! Domains. xenstored_port [Unix. O_RDWR ; Unix. O_CREAT ] 0o600
16+ in
17+ let _ = Unix. write_substring fd " 0" 0 1 in
18+ Unix. close fd ;
19+ Domains. xenstored_kva := " /tmp/kva" ;
20+ let fd =
21+ Unix. openfile ! Domains. xenstored_kva [Unix. O_RDWR ; Unix. O_CREAT ] 0o600
22+ in
23+ Unix. close fd
24+
1225let create_dom0_conn cons doms =
1326 (* NOTE: We can't use Domains.create0 since that opens several files
1427 unavailable in the test env *)
@@ -434,11 +447,8 @@ let test_transaction_watches () =
434447 let actual = Xenbus.Xb. unsafe_pop_output dom0.xb in
435448 check_result actual (Transaction_end , [" OK" ])
436449
437- (* Check that @introduceDomain and @releaseDomain watches appear on respective calls *)
438- let test_introduce_release_watches () =
439- let store, doms, cons = initialize () in
440- let dom0 = create_dom0_conn cons doms in
441-
450+ let register_spec_watches store cons doms dom0 =
451+ (* Register both special watches *)
442452 run store cons doms
443453 [(dom0, none, (Watch , [" @introduceDomain" ; " token" ]), (Watch , [" OK" ]))] ;
444454 assert_watches dom0 [(" @introduceDomain" , " token" , None )] ;
@@ -450,7 +460,14 @@ let test_introduce_release_watches () =
450460 assert_watches dom0
451461 [(" @releaseDomain" , " token" , None ); (" @introduceDomain" , " token" , None )] ;
452462 (* One Watchevent is fired immediately after adding the watch unconditionally *)
453- check_for_watchevent dom0 " @releaseDomain" " token" ;
463+ check_for_watchevent dom0 " @releaseDomain" " token"
464+
465+ (* Check that @introduceDomain and @releaseDomain watches appear on respective calls *)
466+ let test_introduce_release_watches () =
467+ let store, doms, cons = initialize () in
468+ let dom0 = create_dom0_conn cons doms in
469+
470+ register_spec_watches store cons doms dom0 ;
454471
455472 (* Watchevent is pushed to the queue first, then Introduce *)
456473 run store cons doms
@@ -470,6 +487,67 @@ let test_introduce_release_watches () =
470487 let actual = Xenbus.Xb. unsafe_pop_output dom0.xb in
471488 check_result actual (Release , [" OK" ])
472489
490+ (* Check that @introduceDomain and @releaseDomain watches appear on domains dying *)
491+ let test_introduce_release_watches_on_domain_death () =
492+ (* Only the Xenstored.main loop checks for domains dying, so we need to
493+ do special handling here unlike any other unit test *)
494+ initialize_main_loop () ;
495+ let one_loop_iteration, store, cons, doms = Xenstored. main () in
496+ let dom0 = Hashtbl. find cons.domains 0 in
497+
498+ register_spec_watches store cons doms dom0 ;
499+
500+ (* Domains in [1000; 2000] are considered shutdown on the first query *)
501+ let _ = create_domU_conn cons doms 1001 in
502+ (* Check that a @releaseDomain watch event is sent when a domain shuts down *)
503+ one_loop_iteration () ;
504+ let actual = Xenbus.Xb. unsafe_pop_output dom0.xb in
505+ check_result actual (Watchevent , [" @releaseDomain" ; " token" ]) ;
506+ check_no_watchevents dom0 ;
507+
508+ (* Domains > 2000 are considered dead on the first query *)
509+ let _ = create_domU_conn cons doms 2001 in
510+ let _ = create_domU_conn cons doms 2002 in
511+
512+ (* Check that only a single @releaseDomain watch event is sent
513+ when multiple domains die *)
514+ one_loop_iteration () ;
515+ let actual = Xenbus.Xb. unsafe_pop_output dom0.xb in
516+ check_result actual (Watchevent , [" @releaseDomain" ; " token" ]) ;
517+ check_no_watchevents dom0 ;
518+
519+ (* Register a releaseDomain with depth=1 *)
520+ run store cons doms
521+ [
522+ ( dom0
523+ , none
524+ , (Watch , [" @releaseDomain" ; " tokendepth" ; " 1" ])
525+ , (Watch , [" OK" ])
526+ )
527+ ] ;
528+ assert_watches dom0
529+ [
530+ (" @releaseDomain" , " tokendepth" , Some 1 )
531+ ; (" @releaseDomain" , " token" , None )
532+ ; (" @introduceDomain" , " token" , None )
533+ ] ;
534+ (* One Watchevent is fired immediately after adding the watch unconditionally *)
535+ check_for_watchevent dom0 " @releaseDomain" " tokendepth" ;
536+
537+ (* Verify that detailed watch events are sent when multiple domains die *)
538+ let _ = create_domU_conn cons doms 2003 in
539+ let _ = create_domU_conn cons doms 2004 in
540+ one_loop_iteration () ;
541+ let actual = Xenbus.Xb. unsafe_pop_output dom0.xb in
542+ check_result actual (Watchevent , [" @releaseDomain/2004" ; " tokendepth" ]) ;
543+ let actual = Xenbus.Xb. unsafe_pop_output dom0.xb in
544+ check_result actual (Watchevent , [" @releaseDomain" ; " token" ]) ;
545+ let actual = Xenbus.Xb. unsafe_pop_output dom0.xb in
546+ check_result actual (Watchevent , [" @releaseDomain/2003" ; " tokendepth" ]) ;
547+ let actual = Xenbus.Xb. unsafe_pop_output dom0.xb in
548+ check_result actual (Watchevent , [" @releaseDomain/1001" ; " tokendepth" ]) ;
549+ check_no_watchevents dom0
550+
473551(* Check that rm generates recursive watches *)
474552let test_recursive_rm_watch () =
475553 let store, doms, cons = initialize () in
@@ -876,6 +954,10 @@ let () =
876954 , `Quick
877955 , test_introduce_release_watches
878956 )
957+ ; ( " test_introduce_release_watches_on_domain_death"
958+ , `Quick
959+ , test_introduce_release_watches_on_domain_death
960+ )
879961 ; (" test_recursive_rm_watch" , `Quick , test_recursive_rm_watch)
880962 ; (" test_no_watch_on_error" , `Quick , test_no_watch_on_error)
881963 ; (" test_watches_depth" , `Quick , test_watches_depth)
0 commit comments