starry-process 0.4.13

Process management for Starry OS
Documentation
use std::sync::Arc;

use starry_process::init_proc;

mod common;
use common::ProcessExt;

#[test]
fn child() {
    let parent = init_proc();
    let child = parent.new_child();
    assert!(Arc::ptr_eq(&parent, &child.parent().unwrap()));
    assert!(parent.children().iter().any(|c| Arc::ptr_eq(c, &child)));
}

#[test]
fn exit() {
    let parent = init_proc();
    let child = parent.new_child();
    child.exit();
    assert!(child.is_zombie());
    assert!(parent.children().iter().any(|c| Arc::ptr_eq(c, &child)));
}

#[test]
#[should_panic]
fn free_not_zombie() {
    init_proc().new_child().free();
}

#[test]
fn free() {
    let parent = init_proc().new_child();
    let child = parent.new_child();
    child.exit();
    child.free();
    assert!(parent.children().is_empty());
}

#[test]
fn reap() {
    let init = init_proc();

    let parent = init.new_child();
    let child = parent.new_child();

    parent.exit();
    assert!(Arc::ptr_eq(&init, &child.parent().unwrap()));
}

#[test]
fn child_subreaper_flag_is_process_local() {
    let parent = init_proc().new_child();
    assert!(!parent.is_child_subreaper());

    parent.set_child_subreaper(true);
    assert!(parent.is_child_subreaper());

    let child = parent.new_child();
    assert!(!child.is_child_subreaper());

    parent.set_child_subreaper(false);
    assert!(!parent.is_child_subreaper());
}

#[test]
fn reap_to_nearest_child_subreaper() {
    let subreaper = init_proc().new_child();
    subreaper.set_child_subreaper(true);

    let parent = subreaper.new_child();
    let child = parent.new_child();

    parent.exit();

    assert!(Arc::ptr_eq(&subreaper, &child.parent().unwrap()));
    assert!(subreaper.children().iter().any(|c| Arc::ptr_eq(c, &child)));
    assert!(!parent.children().iter().any(|c| Arc::ptr_eq(c, &child)));
}

#[test]
fn reap_to_nearest_nested_child_subreaper() {
    let outer = init_proc().new_child();
    outer.set_child_subreaper(true);

    let inner = outer.new_child();
    inner.set_child_subreaper(true);

    let parent = inner.new_child();
    let child = parent.new_child();

    parent.exit();

    assert!(Arc::ptr_eq(&inner, &child.parent().unwrap()));
}

#[test]
fn exiting_child_subreaper_reparents_to_next_subreaper() {
    let outer = init_proc().new_child();
    outer.set_child_subreaper(true);

    let inner = outer.new_child();
    inner.set_child_subreaper(true);

    let parent = inner.new_child();
    let child = parent.new_child();

    parent.exit();
    assert!(Arc::ptr_eq(&inner, &child.parent().unwrap()));

    inner.exit();
    assert!(Arc::ptr_eq(&outer, &child.parent().unwrap()));
}

#[test]
fn thread_exit() {
    let parent = init_proc();
    let child = parent.new_child();

    child.add_thread(101);
    child.add_thread(102);

    let mut threads = child.threads();
    threads.sort();
    assert_eq!(threads, vec![101, 102]);

    let last = child.exit_thread(101, 7);
    assert!(!last);
    assert_eq!(child.exit_code(), 7);

    let mut snapshot = child.start_group_exit(9).unwrap();
    snapshot.sort();
    assert_eq!(snapshot, vec![102]);
    assert!(child.is_group_exited());

    let last2 = child.exit_thread(102, 3);
    assert!(last2);
    assert_eq!(child.exit_code(), 9);
    assert!(child.start_group_exit(11).is_none());
    assert_eq!(child.exit_code(), 9);
}