From 78b7e942d77e0deb642a3c03b7b6933f72e48712 Mon Sep 17 00:00:00 2001 From: Yashodhan Joshi Date: Thu, 6 Jan 2022 16:30:19 +0530 Subject: [PATCH] Add runtime test crate and integrate it with integration tests --- .../integration_tests_validation.yaml | 4 +- .gitignore | 1 + Cargo.lock | 4 + build.sh | 11 + crates/integration_test/Cargo.lock | 757 ------------------ crates/integration_test/README.md | 26 +- crates/integration_test/run_tests.sh | 18 - crates/integration_test/src/main.rs | 33 +- .../readonly_paths/readonly_paths_tests.rs | 8 +- crates/integration_test/src/utils/mod.rs | 3 +- crates/integration_test/src/utils/support.rs | 9 + .../integration_test/src/utils/test_utils.rs | 79 +- crates/integration_test/tests.sh | 36 + crates/runtimetest/Cargo.toml | 8 + crates/runtimetest/README.md | 41 + crates/runtimetest/src/main.rs | 3 + docs/src/SUMMARY.md | 1 + docs/src/developer/integration_test.md | 13 + docs/src/developer/runtimetest.md | 41 + 19 files changed, 258 insertions(+), 838 deletions(-) delete mode 100644 crates/integration_test/Cargo.lock delete mode 100755 crates/integration_test/run_tests.sh create mode 100755 crates/integration_test/tests.sh create mode 100644 crates/runtimetest/Cargo.toml create mode 100644 crates/runtimetest/README.md create mode 100644 crates/runtimetest/src/main.rs create mode 100644 docs/src/developer/runtimetest.md diff --git a/.github/workflows/integration_tests_validation.yaml b/.github/workflows/integration_tests_validation.yaml index 02bdb1e1..687ebfa7 100644 --- a/.github/workflows/integration_tests_validation.yaml +++ b/.github/workflows/integration_tests_validation.yaml @@ -36,6 +36,6 @@ jobs: - run: sudo apt-get -y update - run: sudo apt-get install -y pkg-config libsystemd-dev libdbus-glib-1-dev libelf-dev libseccomp-dev - name: Validate tests on runc - run: cd ./crates/integration_test && ./run_tests.sh runc + run: cd ./crates/integration_test && ./tests.sh run runc - name: Validate tests on youki - run: cd ./crates/integration_test && ./run_tests.sh ./youki + run: cd ./crates/integration_test && ./tests.sh run ./youki diff --git a/.gitignore b/.gitignore index fc143149..468e4aff 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ tags.temp youki !youki/ youki_integration_test +runtimetest .vscode diff --git a/Cargo.lock b/Cargo.lock index 23217e50..8a4998b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1290,6 +1290,10 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +[[package]] +name = "runtimetest" +version = "0.0.1" + [[package]] name = "rustc_version" version = "0.4.0" diff --git a/build.sh b/build.sh index e12f16a3..bd99d05f 100755 --- a/build.sh +++ b/build.sh @@ -11,7 +11,18 @@ if [ "$1" == "--release" ]; then VERSION=release fi +# We have to build the three binaries seprately for the following reason : +# The runtimetest MUST be compiled from its own directory, if compiled from root, +# it will not work as intended to test the runtime from inside +# So we just compile all thre binaries separately. +# To see why runtime test must be compiled in its own directory, see its Readme or its docs + +cargo build --bin youki --verbose $TGT $1 +cargo build --bin integration_test --verbose $TGT $1 +cd crates/runtimetest cargo build --verbose $TGT $1 +cd ../../ cp target/$TARGET/$VERSION/youki . cp target/$TARGET/$VERSION/integration_test ./youki_integration_test +cp target/$TARGET/$VERSION/runtimetest ./runtimetest diff --git a/crates/integration_test/Cargo.lock b/crates/integration_test/Cargo.lock deleted file mode 100644 index 8c807c3d..00000000 --- a/crates/integration_test/Cargo.lock +++ /dev/null @@ -1,757 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "anyhow" -version = "1.0.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1" - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "cc" -version = "1.0.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" -dependencies = [ - "libc", - "num-integer", - "num-traits", - "time", - "winapi", -] - -[[package]] -name = "clap" -version = "3.0.0-beta.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd1061998a501ee7d4b6d449020df3266ca3124b941ec56cf2005c3779ca142" -dependencies = [ - "bitflags", - "clap_derive", - "indexmap", - "lazy_static", - "os_str_bytes", - "strsim", - "textwrap", - "unicode-width", - "vec_map", -] - -[[package]] -name = "clap_derive" -version = "3.0.0-beta.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "370f715b81112975b1b69db93e0b56ea4cd4e5002ac43b2da8474106a54096a1" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "crc32fast" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845" -dependencies = [ - "cfg-if", - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" -dependencies = [ - "cfg-if", - "crossbeam-utils", - "lazy_static", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" -dependencies = [ - "cfg-if", - "lazy_static", -] - -[[package]] -name = "darling" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f2c43f534ea4b0b049015d00269734195e6d3f0f6635cb692251aca6f9f8b3c" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a" -dependencies = [ - "darling_core", - "quote", - "syn", -] - -[[package]] -name = "derive_builder" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d13202debe11181040ae9063d739fa32cfcaaebe2275fe387703460ae2365b30" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66e616858f6187ed828df7c64a6d71720d83767a7f19740b2d1b6fe6327b36e5" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "derive_builder_macro" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58a94ace95092c5acb1e97a7e846b310cfbd499652f72297da7493f618a98d73" -dependencies = [ - "derive_builder_core", - "syn", -] - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "filetime" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "winapi", -] - -[[package]] -name = "flate2" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" -dependencies = [ - "cfg-if", - "crc32fast", - "libc", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "getrandom" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "getset" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b328c01a4d71d2d8173daa93562a73ab0fe85616876f02500f53d82948c504" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "indexmap" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b2f96d100e1cf1929e7719b7edb3b90ab5298072638fccd77be9ce942ecdfce" - -[[package]] -name = "memoffset" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" -dependencies = [ - "autocfg", -] - -[[package]] -name = "miniz_oxide" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" -dependencies = [ - "adler", - "autocfg", -] - -[[package]] -name = "num-integer" -version = "0.1.44" -name = "nix" -version = "0.22.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3bb9a13fa32bc5aeb64150cd3f32d6cf4c748f8f8a417cce5d2eb976a8370ba" -dependencies = [ - "bitflags", - "cc", - "cfg-if", - "libc", - "memoffset", -] - -[[package]] -name = "oci-spec" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", -] - -[[package]] -name = "oci-spec" -version = "0.5.2" -source = "git+https://github.com/containers/oci-spec-rs?rev=3d5132a18c305be59d58187201429d8f0243b513#3d5132a18c305be59d58187201429d8f0243b513" -dependencies = [ - "derive_builder", - "getset", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "once_cell" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" - -[[package]] -name = "os_str_bytes" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85" - -[[package]] -name = "ppv-lite86" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741" - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "procfs" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2e7eea7c1d7beccbd5acc1e37ac844afccf176525674aad26ece3de1fc7733" -dependencies = [ - "bitflags", - "byteorder", - "chrono", - "flate2", - "hex", - "lazy_static", - "libc", -] - -[[package]] -name = "quote" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - -[[package]] -name = "redox_syscall" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" -dependencies = [ - "bitflags", -] - -[[package]] -name = "ryu" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "serde" -version = "1.0.130" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.130" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "tar" -version = "0.4.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f5515d3add52e0bbdcad7b83c388bb36ba7b754dda3b5f5bc2d38640cdba5c" -dependencies = [ - "filetime", - "libc", - "xattr", -] - -[[package]] -name = "test_framework" -version = "0.1.0" -dependencies = [ - "anyhow", - "crossbeam", -] - -[[package]] -name = "textwrap" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "203008d98caf094106cfaba70acfed15e18ed3ddb7d94e49baec153a2b462789" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "thiserror" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "time" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "unicode-segmentation" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" - -[[package]] -name = "unicode-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "uuid" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "version_check" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "which" -version = "4.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9" -dependencies = [ - "either", - "lazy_static", - "libc", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "xattr" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" -dependencies = [ - "libc", -] - -[[package]] -name = "youki_integration_test" -version = "0.1.0" -dependencies = [ - "anyhow", - "clap", - "clap_derive", - "flate2", - "nix", - "oci-spec", - "once_cell", - "procfs", - "rand", - "serde", - "serde_json", - "tar", - "test_framework", - "uuid", - "which", -] diff --git a/crates/integration_test/README.md b/crates/integration_test/README.md index 87ec8f8d..e875cb48 100644 --- a/crates/integration_test/README.md +++ b/crates/integration_test/README.md @@ -46,8 +46,9 @@ This framework also has some test utils, meant to help doing common operations i - kill_container: runs the runtime command with kill argument, with given id and with given bundle directory - delete_container : runs the runtime command with delete argument, with given id and with given bundle directory - get_state : runs the runtime command with state argument, with given id and with given bundle directory -- test_outside_container : this is meant to mimic [validateOutsideContainer](https://github.com/opencontainers/runtime-tools/blob/59cdde06764be8d761db120664020f0415f36045/validation/util/test.go#L263) function of original tests. -- check_container_created: this checks if the container was created succesfully. +- test_outside_container : this is meant to mimic [RuntimeOutsideValidate](https://github.com/opencontainers/runtime-tools/blob/59cdde06764be8d761db120664020f0415f36045/validation/util/test.go#L263) function of original tests. +- test_inside_container : this is meant to mimic [RuntimeInsideValidate](https://github.com/opencontainers/runtime-tools/blob/59cdde06764be8d761db120664020f0415f36045/validation/util/test.go#L180) function of original tests. +- check_container_created: this checks if the container was created successfully. - test_result!: this is a macro, that allows you to convert from a Result to a TestResult Note that even though all of the above functions are provided, most of the time the only required function is test_outside_container, as it does all the work of setting up the bundle, creating and running the container, getting the state of the container, killing the container and then deleting the container. @@ -73,25 +74,6 @@ Usually the test creation workflow will be something like : This lists some of the things that can be tricky, and can cause issues in running tests. **In case you encounter something, please update this list**. -- The create command should always have its stdout and stderror as null, and should always be waited by `wait`, and not `wait_with_output` on it after spawning. The reason is, runtime process forks itself to create the container, and then keeps running to start, get state etc for the container. Thus if we try to `wait_with_output` on it, it hangs until that process keeps running. Trying to kill tests by `Ctrl+C` will cause the system to stay in modified state (/tmp directories, cgroup directories etc). In case you do this and need to end tests, open a new terminal and send a kill signal to the runtime process, that way it will exit and tests will continue. +- The create command should be waited by `wait`, and not `wait_with_output` on it after spawning if you are simply creating the container. The reason is, runtime process forks itself to create the container, and then keeps running to start the container. Thus if we try to `wait_with_output` on it, without having called `start` on it, it hangs. Trying to kill tests by `Ctrl+C` will cause the system to stay in modified state (/tmp directories, cgroup directories etc). In case you do this and need to end tests, open a new terminal and send a kill signal to the runtime process, that way that youki process will exit and the tests will continue. - The kill and state commands take time. Thus whenever running these, call `wait` or `wait_with_output` on the spawned process to make sure you do not accidentally modify the directories that these use. One example is when running tests, as temp directory deletes itself when dropped, it can cause a race condition when state, or kill command is spawned and not waited. This will cause the directory in /tmp to be deleted first in the drop, and then to get created again due to kill / state command. _In the start of this implementation this problem caused several days to be spent on debugging where the directory in /tmp is getting created from_. - -## Test list - -Update when adding a new test. -Currently, there are the following test groups and tests: - -- lifecycle - - create - - start - - kill - - state - - delete -- create - - empty_id - - valid_id - - duplicate_id -- huge_tlb - - invalid_tlb - - valid_tlb diff --git a/crates/integration_test/run_tests.sh b/crates/integration_test/run_tests.sh deleted file mode 100755 index f73b1666..00000000 --- a/crates/integration_test/run_tests.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -cd ../../ -./build.sh --release -cp ./youki ./crates/integration_test -cp ./youki_integration_test ./crates/integration_test -cd ./crates/integration_test -RUNTIME=./youki -if [[ -n "$1" ]]; then - RUNTIME="$1" -fi -logfile="./test_log.log" -touch $logfile -sudo ./youki_integration_test run -r $RUNTIME > $logfile -if [ 0 -ne $(grep "not ok" $logfile | wc -l ) ]; then - cat $logfile - exit 1 -fi -echo "Validation successful for runtime $RUNTIME" \ No newline at end of file diff --git a/crates/integration_test/src/main.rs b/crates/integration_test/src/main.rs index b82369ca..ff1643ee 100644 --- a/crates/integration_test/src/main.rs +++ b/crates/integration_test/src/main.rs @@ -7,7 +7,7 @@ use crate::tests::pidfile::get_pidfile_test; use crate::tests::readonly_paths::get_ro_paths_test; use crate::tests::seccomp_notify::get_seccomp_notify_test; use crate::tests::tlb::get_tlb_test; -use crate::utils::support::set_runtime_path; +use crate::utils::support::{set_runtime_path, set_runtimetest_path}; use anyhow::{Context, Result}; use clap::Parser; use integration_test::logger; @@ -28,15 +28,20 @@ struct Opts { #[derive(Parser, Debug)] enum SubCommand { + /// run the integration tests Run(Run), + /// list available integration tests List, } #[derive(Parser, Debug)] struct Run { /// Path for the container runtime to be tested - #[clap(short, long)] + #[clap(long)] runtime: PathBuf, + /// Path for the runtimetest binary, which will be used to run tests inside the container + #[clap(long)] + runtimetest: PathBuf, /// Selected tests to be run, format should be /// space separated groups, eg /// -t group1::test1,test3 group2 group3::test5 @@ -107,19 +112,27 @@ fn main() -> Result<()> { Ok(()) } -fn run(opts: &Run, test_manager: &TestManager) -> Result<()> { - match std::fs::canonicalize(&opts.runtime) { - // runtime path is relative or resolved correctly - Ok(path) => set_runtime_path(&path), - // runtime path is name of program which probably exists in $PATH - Err(_) => match which::which(&opts.runtime) { - Ok(path) => set_runtime_path(&path), +fn get_abs_path(rel_path: &PathBuf) -> PathBuf { + match std::fs::canonicalize(rel_path) { + // path is relative or resolved correctly + Ok(path) => path, + // path is name of program which probably exists in $PATH + Err(_) => match which::which(rel_path) { + Ok(path) => path, Err(e) => { - eprintln!("Error in finding runtime : {}\nexiting.", e); + eprintln!("Error in finding path {:?} : {}\nexiting.", rel_path, e); std::process::exit(66); } }, } +} + +fn run(opts: &Run, test_manager: &TestManager) -> Result<()> { + let runtime_path = get_abs_path(&opts.runtime); + set_runtime_path(&runtime_path); + + let runtimetest_path = get_abs_path(&opts.runtimetest); + set_runtimetest_path(&runtimetest_path); if let Some(tests) = &opts.tests { let tests_to_run = parse_tests(tests); diff --git a/crates/integration_test/src/tests/readonly_paths/readonly_paths_tests.rs b/crates/integration_test/src/tests/readonly_paths/readonly_paths_tests.rs index 807610e4..32fde6d9 100644 --- a/crates/integration_test/src/tests/readonly_paths/readonly_paths_tests.rs +++ b/crates/integration_test/src/tests/readonly_paths/readonly_paths_tests.rs @@ -2,7 +2,7 @@ use crate::utils::test_inside_container; use anyhow::bail; use nix::sys::stat::SFlag; use oci_spec::runtime::LinuxBuilder; -use oci_spec::runtime::{Spec, SpecBuilder}; +use oci_spec::runtime::{ProcessBuilder, Spec, SpecBuilder}; use std::path::PathBuf; use test_framework::{Test, TestGroup, TestResult}; @@ -14,6 +14,12 @@ fn get_spec(readonly_paths: Vec) -> Spec { .build() .expect("could not build"), ) + .process( + ProcessBuilder::default() + .args(vec!["runtimetest".to_string()]) + .build() + .unwrap(), + ) .build() .unwrap() } diff --git a/crates/integration_test/src/utils/mod.rs b/crates/integration_test/src/utils/mod.rs index 69e473c5..68ae575a 100644 --- a/crates/integration_test/src/utils/mod.rs +++ b/crates/integration_test/src/utils/mod.rs @@ -2,7 +2,8 @@ pub mod support; pub mod temp_dir; pub mod test_utils; pub use support::{ - generate_uuid, get_project_path, get_runtime_path, prepare_bundle, set_config, set_runtime_path, + generate_uuid, get_project_path, get_runtime_path, get_runtimetest_path, prepare_bundle, + set_config, set_runtime_path, }; pub use temp_dir::{create_temp_dir, TempDir}; pub use test_utils::{ diff --git a/crates/integration_test/src/utils/support.rs b/crates/integration_test/src/utils/support.rs index 0dafdcd8..c8901260 100644 --- a/crates/integration_test/src/utils/support.rs +++ b/crates/integration_test/src/utils/support.rs @@ -11,6 +11,7 @@ use tar::Archive; use uuid::Uuid; static RUNTIME_PATH: OnceCell = OnceCell::new(); +static RUNTIMETEST_PATH: OnceCell = OnceCell::new(); pub fn set_runtime_path(path: &Path) { RUNTIME_PATH.set(path.to_owned()).unwrap(); @@ -20,6 +21,14 @@ pub fn get_runtime_path() -> &'static PathBuf { RUNTIME_PATH.get().expect("Runtime path is not set") } +pub fn set_runtimetest_path(path: &Path) { + RUNTIMETEST_PATH.set(path.to_owned()).unwrap(); +} + +pub fn get_runtimetest_path() -> &'static PathBuf { + RUNTIMETEST_PATH.get().expect("Runtimetest path is not set") +} + #[allow(dead_code)] pub fn get_project_path() -> PathBuf { let current_dir_path_result = env::current_dir(); diff --git a/crates/integration_test/src/utils/test_utils.rs b/crates/integration_test/src/utils/test_utils.rs index 0c16db45..4accf9fb 100644 --- a/crates/integration_test/src/utils/test_utils.rs +++ b/crates/integration_test/src/utils/test_utils.rs @@ -1,7 +1,7 @@ use super::{generate_uuid, prepare_bundle, set_config}; ///! Contains utility functions for testing ///! Similar to https://github.com/opencontainers/runtime-tools/blob/master/validation/util/test.go -use super::{get_runtime_path, TempDir}; +use super::{get_runtime_path, get_runtimetest_path, TempDir}; use anyhow::{anyhow, bail, Context, Result}; use oci_spec::runtime::Spec; use serde::{Deserialize, Serialize}; @@ -45,9 +45,13 @@ pub struct ContainerData { /// Starts the runtime with given directory as root directory pub fn create_container>(id: &Uuid, dir: P) -> Result { let res = Command::new(get_runtime_path()) - .stdin(Stdio::null()) - .stdout(Stdio::null()) - .stderr(Stdio::null()) + // set stdio so that we can get o/p of runtimetest + // in test_inside_container function + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + // set log level to error only, otherwise + // we get warnings in stderr + .env("YOUKI_LOG_LEVEL", "error") .arg("--root") .arg(dir.as_ref().join("runtime")) .arg("create") @@ -105,8 +109,6 @@ pub fn get_state>(id: &Uuid, dir: P) -> Result<(String, String)> pub fn start_container>(id: &Uuid, dir: P) -> Result { let res = Command::new(get_runtime_path()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) .arg("--root") .arg(dir.as_ref().join("runtime")) .arg("start") @@ -144,36 +146,59 @@ pub fn test_outside_container( // mostly needs a name that better expresses what this actually does pub fn test_inside_container( spec: Spec, - execute_test: &dyn Fn(&TempDir) -> Result<()>, + setup_for_test: &dyn Fn(&TempDir) -> Result<()>, ) -> TestResult { let id = generate_uuid(); let bundle = prepare_bundle(&id).unwrap(); - test_result!(execute_test(&bundle)); + // This will do the required setup for the test + test_result!(setup_for_test(&bundle)); set_config(&bundle, &spec).unwrap(); - let create_result = create_container(&id, &bundle).unwrap().wait(); - let (out, err) = get_state(&id, &bundle).unwrap(); - let state: Option = match serde_json::from_str(&out) { - Ok(v) => Some(v), - Err(_) => None, - }; - let data = ContainerData { - id: id.to_string(), - state, - state_err: err, - create_result, - }; - test_result!(check_container_created(&data)); - let start_result = match start_container(&id, &bundle).unwrap().wait_with_output() { - std::io::Result::Ok(c) => c, - std::io::Result::Err(e) => return TestResult::Failed(anyhow!(e)), + // as we have to run runtimetest inside the container, and is expects + // the config.json to be at path /config.json we save it there + let path = bundle + .as_ref() + .join("bundle") + .join("rootfs") + .join("config.json"); + spec.save(path).unwrap(); + + let runtimetest_path = get_runtimetest_path(); + // The config will directly use runtime as the command to be run, so we have to + // save the runtimetest binary at its /bin + std::fs::copy( + runtimetest_path, + bundle + .as_ref() + .join("bundle") + .join("rootfs") + .join("bin") + .join("runtimetest"), + ) + .unwrap(); + let create_process = create_container(&id, &bundle).unwrap(); + // here we do not wait for the process by calling wait() as in the test_outside_container + // function because we need the output of the runtimetest. If we call wait, it will return + // and we won't have an easy way of getting the stdio of the runtimetest. + // Thus to make sure the container is created, we just wait for sometime, and + // assume that the create command was successful. If it wasn't we can catch that error + // in the start_container, as we can not start a non-created container anyways + std::thread::sleep(std::time::Duration::from_millis(2000)); + match start_container(&id, &bundle).unwrap().wait_with_output() { + Ok(c) => c, + Err(e) => return TestResult::Failed(anyhow!("container start failed : {:?}", e)), }; - let stderr = String::from_utf8_lossy(&start_result.stderr); + let create_output = create_process + .wait_with_output() + .context("getting output after starting the container failed") + .unwrap(); + + let stderr = String::from_utf8_lossy(&create_output.stderr); if !stderr.is_empty() { return TestResult::Failed(anyhow!( - "container start stderr was not empty : found {}", + "container stderr was not empty, found : {}", stderr )); } @@ -203,7 +228,7 @@ pub fn check_container_created(data: &ContainerData) -> Result<()> { Ok(exit_status) => { if !exit_status.success() { bail!( - "container creation was not successfull. Exit code was {:?}", + "container creation was not successful. Exit code was {:?}", exit_status.code() ) } diff --git a/crates/integration_test/tests.sh b/crates/integration_test/tests.sh new file mode 100755 index 00000000..a78a9758 --- /dev/null +++ b/crates/integration_test/tests.sh @@ -0,0 +1,36 @@ +#!/bin/bash +cd ../../ +./build.sh --release +cp ./youki ./crates/integration_test/youki +cp ./youki_integration_test ./crates/integration_test/youki_integration_test +cp ./runtimetest ./crates/integration_test/runtimetest +cd ./crates/integration_test + +RUNTIME=./youki + +# syntax is +# test.sh build +# test.sh run +# test.sh run runtime-name + +if [[ "$1" = "build" ]]; then + exit 0 +fi + +# if second argument is non-empty, consider it as runtime name +# else the consider first argument as runtime name +if [[ -n "$2" ]]; then + RUNTIME="$2" +elif [[-n "$1" ]] + RUNTIME="$1" +fi + + +logfile="./test_log.log" +touch $logfile +sudo ./youki_integration_test run --runtime $RUNTIME --runtimetest ./runtimetest > $logfile +if [ 0 -ne $(grep "not ok" $logfile | wc -l ) ]; then + cat $logfile + exit 1 +fi +echo "Validation successful for runtime $RUNTIME" \ No newline at end of file diff --git a/crates/runtimetest/Cargo.toml b/crates/runtimetest/Cargo.toml new file mode 100644 index 00000000..ea84166c --- /dev/null +++ b/crates/runtimetest/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "runtimetest" +version = "0.0.1" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/crates/runtimetest/README.md b/crates/runtimetest/README.md new file mode 100644 index 00000000..ac010dec --- /dev/null +++ b/crates/runtimetest/README.md @@ -0,0 +1,41 @@ +# Runtime test + +This is the binary which runs the tests inside the container process, and checks that constraints and restrictions are upheld from inside the container. + +This is primarily used from the `test_inside_container` function related tests in the integration tests. + +## Conventions + +The main function will call the different tests functions, one by one to check that all required guarantees hold. This might be parallelized in future, but initially the tests are run serially. + +The path of config spec will always be /spec.json , and this is fixed so that no additional env or cmd arg is required, and we don't need to depend on clap or manual parsing for that. + +Make sure to consider failure cases, and try not to panic from any functions. If any error occur, or if some test fails, then it should write the error to the stderr, and return. The integration test will check stderr to be empty as an indication of all tests passing, and in case stderr is not empty, it will consider some test to be failing, and show the error as the contents of stderr. Thus make sure to include enough information in stderr message from failing tests to understand what failed in which test. +There is currently no convention of explicit indication of tests passing, the passing test may write `OK` or something similar to stdout, but as of now, the stdout will be completely ignored by integration test. + +## Special Notes + +This package must be compiled as a statically linked binary, as otherwise the rust compile will make it dynamically link to /lib64/ld-linux-x86-64.so , which is not available inside the container, and thus making the binary not usable inside the container process. + +**Note** that the dynamically linked binary does not give a `segmentation fault` or similar error when tried to run inside the container, but instead gives `no such file or directory found` or `executable not found` error, even though the executable exists in the container. This made this tricky to debug correctly when originally developing, so if you decide on chaing the compilation or configuration of this , please make absolutely sure that the changes work and do not accidentally break something. + +**Another Note** is that `cargo build` must be run from inside this directory only to make the binary be a statically linked binary. This is due to the fact that to make it statically linked, appropriate rustflags must be set in the .cargo/config.toml . But in case of a workspace, as like this, when run `cargo build` from project root, it ignores crate specific config, and only checks the project root .cargo/config , which currently does not allow setting rustflags for specific crate, which means either all binaries must be statically linked, or none can be. Thus currently the only way is to run the build command inside this directory. + +you can use + +```bash +readelf -l path/to/binary | grep "program interpreter" # should give empty output +file path/to/binary # should specify statically linked in output +``` + +to find out if the binary is dynamically or statically linked. + +Reading the Readme of integration tests can be helpful to understand how the integration tests and the runtime tests interoperate with one another. + +see + +https://stackoverflow.com/questions/31770604/how-to-generate-statically-linked-executables +https://superuser.com/questions/248512/why-do-i-get-command-not-found-when-the-binary-file-exists +https://doc.rust-lang.org/cargo/reference/config.html + +for more info diff --git a/crates/runtimetest/src/main.rs b/crates/runtimetest/src/main.rs new file mode 100644 index 00000000..2103ca8a --- /dev/null +++ b/crates/runtimetest/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("This is where the internal tests will go later..."); +} diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 10de2053..c910a8db 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -28,3 +28,4 @@ - [youki](./developer/youki.md) - [test_framework](./developer/test_framework.md) - [integration_test](./developer/integration_test.md) + - [runtimetest](./developer/runtimetest.md) diff --git a/docs/src/developer/integration_test.md b/docs/src/developer/integration_test.md index dc5a4c4d..94999c3f 100644 --- a/docs/src/developer/integration_test.md +++ b/docs/src/developer/integration_test.md @@ -7,3 +7,16 @@ Other than that, those tests also showed some issues while running on some local Thus we decided to port the tests to Rust, and validate them, so that we have a set of unit tests as well of integration tests to validate the working of runtime. These tests are still under development, and you can check the [tracking issue](https://github.com/containers/youki/issues/361) for more details. More details on working of these tests can be found at [https://github.com/containers/youki/tree/main/crates/integration_test](https://github.com/containers/youki/tree/main/crates/integration_test). As these tests are under development, these are validated on a standard runtime such as runc in the GitHub CI, so validate the tests themselves. + +## Notes + +### About the create container function + +The test_utils provides a create_container function which can be used to run the `youki create` command. It returns the child process struct, which can be either `wait()` or `wait_with_output()` to wait for it finishing. Unless you know what are you doing, it is recommended to call `wait()` on it, as otherwise the process will hang. As explained in the [youki docs](../youki.md) , the `youki create` process, after starting forks, and the forked process keeps waiting for another youki process to send it the `start` signal , and after receiving it, that forked process execs the container program. If you are simply trying to create a container, such as in case of `test_outside_runtime` then calling `wait_with_output()` will cause it to hand. If you are actually going to start a container, and need output from the container process, then you must keep the `Child struct` returned by `create` function and call `wait_with_output()` on it **AFTER** you have called the start command on that container, which will give you the `stdout` and `stderr` of the process running inside the container. + +To understand how this works, take a look at [handling stdio](https://github.com/opencontainers/runc/blob/master/docs/terminals.md) of the runc, specially the [detached pass-through mode](https://github.com/opencontainers/runc/blob/master/docs/terminals.md#detached-pass-through) section. As explained in it, we setup the stdio for the original youki process in `youki create` by setting the stdio to `Stdio::piped()` in the `create` function. then we set the `terminal` option to `false` (which is the default anyways) in the spec, which makes it run in the pass-through mode. Then when the create process is done its work, and its forked process is waiting for the start signal, it uses the same stdio pipes. Thus calling `wait_with_output()` without starting will keep it hanged up, and after calling start, stdio of the program to be run inside the container can be obtained from the `youki create`'s process. + +### How test inside container works + +We use test_inside_container for making sure that the restrictions and constraints are uphold from inside the container process. +For that, first whichever integration test needs to use it, must define the runtimetest as the container process in the spec, and then use `test_inside_container` function. It requires a function which will do the necessary setup for the tests that are to be run inside. Then the counterpart for the test should be added to the `runtimetest` crate, which will run inside the container and and if there is any error, print it to the `stderr`. The `test_inside_container` function will wait for the tests to be over and then check the `stderr` to be empty. If it is not, the the test is assumed to fail. diff --git a/docs/src/developer/runtimetest.md b/docs/src/developer/runtimetest.md new file mode 100644 index 00000000..d5fc89af --- /dev/null +++ b/docs/src/developer/runtimetest.md @@ -0,0 +1,41 @@ +# Runtime Test + +This crate provides a binary which is used by integration tests to verify that the restrictions and constraints applied to the container are upheld by the container process, from inside the container process. This runs the tests one-by-one, and the failing test prints the error to the stderr. + +## Notes + +This binary must be compiled with the option of static linking to crt0 given to the rustc. If compiled without it, it will add a linking to /lib64/ld-linux-x86-64.so . The binary compiled this way cannot be run inside the container process, as they do not have access to /lib64/... Thus the runtime test must be statically linked to crt0. + +Also this option can be given through .cargo/config.toml rustflags option, but this works only if the cargo build is invoked within the runtimetest directory. If invoked from the project root, the .cargo/config in the project root will take preference and the rustflags will be ignored. + +To see if a binary can be run inside the container process, run + +```console +readelf -l path/to/binary |grep "program interpreter" +``` + +`[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]` means that the binary is not statically linked, and cannot be run inside the container process. If the above command gives no output, that means it does not require any program interpreter and can be run inside the container. + +Another way is to run + +```console +file path/to/binary +``` + +```console +./youki: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=...., for GNU/Linux 3.2.0, with debug_info, not stripped` +``` + +This output indicates that the binary is dynamically linked, thus cannot be run inside the container process + +```console +./runtimetest: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=...., for GNU/Linux 3.2.0, with debug_info, not stripped +``` + +This output indicates that the binary is statically linked, and can be run inside the container process + +Some links to help : + +- [how to generate static executable](https://stackoverflow.com/questions/31770604/how-to-generate-statically-linked-executables) +- [understanding the error which dynamically linked library gives](https://superuser.com/questions/248512/why-do-i-get-command-not-found-when-the-binary-file-exists) +- [Rust cargo config for rustflags](https://doc.rust-lang.org/cargo/reference/config.html)