From 2e11d9e14ce1a2cf0353363e4239a9d1fa147694 Mon Sep 17 00:00:00 2001
From: Bryant Mairs <bryant@mai.rs>
Date: Thu, 10 Aug 2017 10:33:19 -0700
Subject: [PATCH] Add more fcntl and seal constants for Android/Linux

We now create an additional binary `linux_fcntl` for testing this
since there are header conflicts when including all necessary headers.
This binary is run on all platforms even though it's empty on all non-
Android/non-Linux platforms.

Testing has been switched from a custom binary to using a runner-less
test (or pair of tests). This means that for local development a simple
`cd libc-test && cargo test` will run all the tests. CI has also been
updated here to reflect that.
---
 README.md                       |  2 +-
 appveyor.yml                    |  2 +-
 ci/run.sh                       | 59 +++++++++++++++++++++++----------
 libc-test/Cargo.toml            | 10 ++++++
 libc-test/build.rs              | 33 +++++++++++++++++-
 libc-test/test/linux_fcntl.rs   |  6 ++++
 libc-test/{src => test}/main.rs |  2 +-
 src/macros.rs                   | 37 ---------------------
 src/unix/notbsd/mod.rs          |  8 +++++
 9 files changed, 100 insertions(+), 59 deletions(-)
 create mode 100644 libc-test/test/linux_fcntl.rs
 rename libc-test/{src => test}/main.rs (60%)

diff --git a/README.md b/README.md
index 67535d21..7b2d778e 100644
--- a/README.md
+++ b/README.md
@@ -93,7 +93,7 @@ With that in mind, the steps for adding a new API are:
 We have two automated tests running on [Travis](https://travis-ci.org/rust-lang/libc):
 
 1. [`libc-test`](https://github.com/alexcrichton/ctest)
-  - `cd libc-test && cargo run`
+  - `cd libc-test && cargo test`
   - Use the `skip_*()` functions in `build.rs` if you really need a workaround.
 2. Style checker
   - `rustc ci/style.rs && ./style src`
diff --git a/appveyor.yml b/appveyor.yml
index 22ef8a56..3121825b 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -24,7 +24,7 @@ build: false
 
 test_script:
   - cargo test --target %TARGET%
-  - cargo run --manifest-path libc-test/Cargo.toml --target %TARGET%
+  - cargo test --manifest-path libc-test/Cargo.toml --target %TARGET%
 
 cache:
   - target
diff --git a/ci/run.sh b/ci/run.sh
index 1b8226e5..d9dddfa3 100755
--- a/ci/run.sh
+++ b/ci/run.sh
@@ -70,12 +70,14 @@ fi
 
 case "$TARGET" in
   *-apple-ios)
-    cargo rustc --manifest-path libc-test/Cargo.toml --target $TARGET -- \
-        -C link-args=-mios-simulator-version-min=7.0
+    cargo rustc --manifest-path libc-test/Cargo.toml --target $TARGET \
+        --test main -- -C link-args=-mios-simulator-version-min=7.0
+    cargo rustc --manifest-path libc-test/Cargo.toml --target $TARGET \
+        --test linux-fcntl -- -C link-args=-mios-simulator-version-min=7.0
     ;;
 
   *)
-    cargo build --manifest-path libc-test/Cargo.toml --target $TARGET
+    cargo build --manifest-path libc-test/Cargo.toml --target $TARGET --tests
     ;;
 esac
 
@@ -95,61 +97,81 @@ case "$TARGET" in
     fi
     emulator @$arch -no-window $accel &
     adb wait-for-device
-    adb push $CARGO_TARGET_DIR/$TARGET/debug/libc-test /data/local/tmp/libc-test
-    adb shell /data/local/tmp/libc-test 2>&1 | tee /tmp/out
+    adb push $CARGO_TARGET_DIR/$TARGET/debug/main-* /data/local/tmp/main
+    adb shell /data/local/tmp/main 2>&1 | tee /tmp/out
+    grep "^PASSED .* tests" /tmp/out
+    adb push $CARGO_TARGET_DIR/$TARGET/debug/linux_fcntl-* /data/local/tmp/linux_fcntl
+    adb shell /data/local/tmp/linux_fcntl 2>&1 | tee /tmp/out
     grep "^PASSED .* tests" /tmp/out
     ;;
 
   i386-apple-ios)
     rustc -O ./ci/ios/deploy_and_run_on_ios_simulator.rs
-    ./deploy_and_run_on_ios_simulator $CARGO_TARGET_DIR/$TARGET/debug/libc-test
+    ./deploy_and_run_on_ios_simulator $CARGO_TARGET_DIR/$TARGET/debug/main-*
+    ./deploy_and_run_on_ios_simulator $CARGO_TARGET_DIR/$TARGET/debug/linux_fcntl-*
     ;;
 
   x86_64-apple-ios)
     rustc -O ./ci/ios/deploy_and_run_on_ios_simulator.rs
-    ./deploy_and_run_on_ios_simulator $CARGO_TARGET_DIR/$TARGET/debug/libc-test
+    ./deploy_and_run_on_ios_simulator $CARGO_TARGET_DIR/$TARGET/debug/main-*
+    ./deploy_and_run_on_ios_simulator $CARGO_TARGET_DIR/$TARGET/debug/linux_fcntl-*
     ;;
 
   arm-unknown-linux-gnueabihf)
-    qemu-arm -L /usr/arm-linux-gnueabihf $CARGO_TARGET_DIR/$TARGET/debug/libc-test
+    qemu-arm -L /usr/arm-linux-gnueabihf $CARGO_TARGET_DIR/$TARGET/debug/main-*
+    qemu-arm -L /usr/arm-linux-gnueabihf $CARGO_TARGET_DIR/$TARGET/debug/linux_fcntl-*
     ;;
 
   mips-unknown-linux-gnu)
-    qemu-mips -L /usr/mips-linux-gnu $CARGO_TARGET_DIR/$TARGET/debug/libc-test
+    qemu-mips -L /usr/mips-linux-gnu $CARGO_TARGET_DIR/$TARGET/debug/main-*
+    qemu-mips -L /usr/mips-linux-gnu $CARGO_TARGET_DIR/$TARGET/debug/linux_fcntl-*
     ;;
 
   mips64-unknown-linux-gnuabi64)
-    qemu-mips64 -L /usr/mips64-linux-gnuabi64 $CARGO_TARGET_DIR/$TARGET/debug/libc-test
+    qemu-mips64 -L /usr/mips64-linux-gnuabi64 $CARGO_TARGET_DIR/$TARGET/debug/main-*
+    qemu-mips64 -L /usr/mips64-linux-gnuabi64 $CARGO_TARGET_DIR/$TARGET/debug/linux_fcntl-*
     ;;
 
   mips-unknown-linux-musl)
     qemu-mips -L /toolchain/staging_dir/toolchain-mips_34kc_gcc-5.3.0_musl-1.1.15 \
-              $CARGO_TARGET_DIR/$TARGET/debug/libc-test
+              $CARGO_TARGET_DIR/$TARGET/debug/main-*
+    qemu-mips -L /toolchain/staging_dir/toolchain-mips_34kc_gcc-5.3.0_musl-1.1.15 \
+              $CARGO_TARGET_DIR/$TARGET/debug/linux_fcntl-*
     ;;
 
   mipsel-unknown-linux-musl)
-      qemu-mipsel -L /toolchain $CARGO_TARGET_DIR/$TARGET/debug/libc-test
+      qemu-mipsel -L /toolchain $CARGO_TARGET_DIR/$TARGET/debug/main-*
+      qemu-mipsel -L /toolchain $CARGO_TARGET_DIR/$TARGET/debug/linux_fcntl-*
       ;;
 
   powerpc-unknown-linux-gnu)
-    qemu-ppc -L /usr/powerpc-linux-gnu $CARGO_TARGET_DIR/$TARGET/debug/libc-test
+    qemu-ppc -L /usr/powerpc-linux-gnu $CARGO_TARGET_DIR/$TARGET/debug/main-*
+    qemu-ppc -L /usr/powerpc-linux-gnu $CARGO_TARGET_DIR/$TARGET/debug/linux_fcntl-*
     ;;
 
   powerpc64-unknown-linux-gnu)
-    qemu-ppc64 -L /usr/powerpc64-linux-gnu $CARGO_TARGET_DIR/$TARGET/debug/libc-test
+    qemu-ppc64 -L /usr/powerpc64-linux-gnu $CARGO_TARGET_DIR/$TARGET/debug/main-*
+    qemu-ppc64 -L /usr/powerpc64-linux-gnu $CARGO_TARGET_DIR/$TARGET/debug/linux_fcntl-*
     ;;
 
   aarch64-unknown-linux-gnu)
-    qemu-aarch64 -L /usr/aarch64-linux-gnu/ $CARGO_TARGET_DIR/$TARGET/debug/libc-test
+    qemu-aarch64 -L /usr/aarch64-linux-gnu/ $CARGO_TARGET_DIR/$TARGET/debug/main-*
+    qemu-aarch64 -L /usr/aarch64-linux-gnu/ $CARGO_TARGET_DIR/$TARGET/debug/linux_fcntl-*
     ;;
 
   s390x-unknown-linux-gnu)
     # TODO: in theory we should execute this, but qemu segfaults immediately :(
-    # qemu-s390x -L /usr/s390x-linux-gnu/ $CARGO_TARGET_DIR/$TARGET/debug/libc-test
+    # qemu-s390x -L /usr/s390x-linux-gnu/ $CARGO_TARGET_DIR/$TARGET/debug/main-*
+    # qemu-s390x -L /usr/s390x-linux-gnu/ $CARGO_TARGET_DIR/$TARGET/debug/linux_fcntl-*
     ;;
 
   *-rumprun-netbsd)
-    rumprun-bake hw_virtio /tmp/libc-test.img $CARGO_TARGET_DIR/$TARGET/debug/libc-test
+    rumprun-bake hw_virtio /tmp/libc-test.img $CARGO_TARGET_DIR/$TARGET/debug/main-*
+    qemu-system-x86_64 -nographic -vga none -m 64 \
+        -kernel /tmp/libc-test.img 2>&1 | tee /tmp/out &
+    sleep 5
+    grep "^PASSED .* tests" /tmp/out
+    rumprun-bake hw_virtio /tmp/libc-test.img $CARGO_TARGET_DIR/$TARGET/debug/linux_fcntl-*
     qemu-system-x86_64 -nographic -vga none -m 64 \
         -kernel /tmp/libc-test.img 2>&1 | tee /tmp/out &
     sleep 5
@@ -157,6 +179,7 @@ case "$TARGET" in
     ;;
 
   *)
-    $CARGO_TARGET_DIR/$TARGET/debug/libc-test
+    $CARGO_TARGET_DIR/$TARGET/debug/main-*
+    $CARGO_TARGET_DIR/$TARGET/debug/linux_fcntl-*
     ;;
 esac
diff --git a/libc-test/Cargo.toml b/libc-test/Cargo.toml
index 4e7c8845..30ea5463 100644
--- a/libc-test/Cargo.toml
+++ b/libc-test/Cargo.toml
@@ -9,3 +9,13 @@ libc = { path = ".." }
 
 [build-dependencies]
 ctest = "0.1"
+
+[[test]]
+name = "main"
+path = "test/main.rs"
+harness = false
+
+[[test]]
+name = "linux-fcntl"
+path = "test/linux_fcntl.rs"
+harness = false
diff --git a/libc-test/build.rs b/libc-test/build.rs
index 6b6e865e..ee30e032 100644
--- a/libc-test/build.rs
+++ b/libc-test/build.rs
@@ -468,6 +468,11 @@ fn main() {
             // it's been fixed in CI.
             "MADV_SOFT_OFFLINE" if mips && linux => true,
 
+            // These constants are tested in a separate test program generated below because there
+            // are header conflicts if we try to include the headers that define them here.
+            "F_CANCELLK" | "F_ADD_SEALS" | "F_GET_SEALS" => true,
+            "F_SEAL_SEAL" | "F_SEAL_SHRINK" | "F_SEAL_GROW" | "F_SEAL_WRITE" => true,
+
             _ => false,
         }
     });
@@ -641,5 +646,31 @@ fn main() {
         }
     });
 
-    cfg.generate("../src/lib.rs", "all.rs");
+    cfg.generate("../src/lib.rs", "main.rs");
+
+    // On Linux or Android also generate another script for testing linux/fcntl declarations.
+    // These cannot be tested normally because including both `linux/fcntl.h` and `fcntl.h`
+    // fails on a lot of platforms.
+    let mut cfg = ctest::TestGenerator::new();
+    cfg.skip_type(|_| true)
+        .skip_struct(|_| true)
+        .skip_fn(|_| true);
+    if android || linux {
+        // musl defines these directly in `fcntl.h`
+        if musl {
+            cfg.header("fcntl.h");
+        } else {
+            cfg.header("linux/fcntl.h");
+        }
+        cfg.skip_const(move |name| {
+            match name {
+                "F_CANCELLK" | "F_ADD_SEALS" | "F_GET_SEALS" => false,
+                "F_SEAL_SEAL" | "F_SEAL_SHRINK" | "F_SEAL_GROW" | "F_SEAL_WRITE" => false,
+                _ => true,
+            }
+        });
+    } else {
+        cfg.skip_const(|_| true);
+    }
+    cfg.generate("../src/lib.rs", "linux_fcntl.rs");
 }
diff --git a/libc-test/test/linux_fcntl.rs b/libc-test/test/linux_fcntl.rs
new file mode 100644
index 00000000..1c4635b1
--- /dev/null
+++ b/libc-test/test/linux_fcntl.rs
@@ -0,0 +1,6 @@
+#![allow(bad_style, improper_ctypes)]
+extern crate libc;
+
+use libc::*;
+
+include!(concat!(env!("OUT_DIR"), "/linux_fcntl.rs"));
diff --git a/libc-test/src/main.rs b/libc-test/test/main.rs
similarity index 60%
rename from libc-test/src/main.rs
rename to libc-test/test/main.rs
index fff188d3..3d336102 100644
--- a/libc-test/src/main.rs
+++ b/libc-test/test/main.rs
@@ -3,4 +3,4 @@ extern crate libc;
 
 use libc::*;
 
-include!(concat!(env!("OUT_DIR"), "/all.rs"));
+include!(concat!(env!("OUT_DIR"), "/main.rs"));
diff --git a/src/macros.rs b/src/macros.rs
index 5811c84c..84294420 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -69,40 +69,3 @@ macro_rules! f {
 macro_rules! __item {
     ($i:item) => ($i)
 }
-
-#[cfg(test)]
-mod tests {
-    cfg_if! {
-        if #[cfg(test)] {
-            use std::option::Option as Option2;
-            fn works1() -> Option2<u32> { Some(1) }
-        } else {
-            fn works1() -> Option<u32> { None }
-        }
-    }
-
-    cfg_if! {
-        if #[cfg(foo)] {
-            fn works2() -> bool { false }
-        } else if #[cfg(test)] {
-            fn works2() -> bool { true }
-        } else {
-            fn works2() -> bool { false }
-        }
-    }
-
-    cfg_if! {
-        if #[cfg(foo)] {
-            fn works3() -> bool { false }
-        } else {
-            fn works3() -> bool { true }
-        }
-    }
-
-    #[test]
-    fn it_works() {
-        assert!(works1().is_some());
-        assert!(works2());
-        assert!(works3());
-    }
-}
diff --git a/src/unix/notbsd/mod.rs b/src/unix/notbsd/mod.rs
index e19c7f21..73eaf4ab 100644
--- a/src/unix/notbsd/mod.rs
+++ b/src/unix/notbsd/mod.rs
@@ -212,9 +212,17 @@ pub const F_SETFL: ::c_int = 4;
 pub const F_SETLEASE: ::c_int = 1024;
 pub const F_GETLEASE: ::c_int = 1025;
 pub const F_NOTIFY: ::c_int = 1026;
+pub const F_CANCELLK: ::c_int = 1029;
 pub const F_DUPFD_CLOEXEC: ::c_int = 1030;
 pub const F_SETPIPE_SZ: ::c_int = 1031;
 pub const F_GETPIPE_SZ: ::c_int = 1032;
+pub const F_ADD_SEALS: ::c_int = 1033;
+pub const F_GET_SEALS: ::c_int = 1034;
+
+pub const F_SEAL_SEAL: ::c_int = 0x0001;
+pub const F_SEAL_SHRINK: ::c_int = 0x0002;
+pub const F_SEAL_GROW: ::c_int = 0x0004;
+pub const F_SEAL_WRITE: ::c_int = 0x0008;
 
 // TODO(#235): Include file sealing fcntls once we have a way to verify them.
 
-- 
GitLab