Repository: google/autocxx (rust)

Issue:
Run test suite & examples on more platforms in CI
Right now our github actions test things on Linux only. The `cxx` crate has actions to test things on all sorts of platforms. We should too.

Pull request:
github actions build and test on major architectures
Fixes #796 

Adds test and examples workflows for ubuntu-latest (stable, beta, nightly), macos nightly, windows nightly (msvc and gnu), tighter clippy, and outdated package notification

* `autocxx-reduce`  and `autocxx-gen` excluded on Windows targets as `creduce` isn't packaged there
* `s2` and `chromium-fake-render-frame-host` examples fail to link on Windows, so excluded there
* `clippy` check is made stronger
* small clippy fixes included to get clippy green
* `outdated` check will generally fail. It should be used for notification, not as a PR-merge requirement
* all checks scheduled daily for 1.40 am
* Several beta integration tests give a compiler panic. This seems to be a known issue #818
* windows test failures ignored #819



Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..64b38df2
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,146 @@
+name: CI
+
+on:
+  push:
+    branches: [main]
+  pull_request:
+  schedule: [cron: "40 1 * * *"]
+
+jobs:
+  test:
+    name: ${{matrix.name || format('Rust {0}', matrix.rust)}}-test
+    runs-on: ${{matrix.os || 'ubuntu'}}-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - rust: nightly
+          - rust: beta
+          - rust: stable
+          - name: macOS
+            rust: nightly
+            os: macos
+          - name: Windows (gnu)
+            rust: nightly-x86_64-pc-windows-gnu
+            os: windows
+          - name: Windows (msvc)
+            rust: nightly-x86_64-pc-windows-msvc
+            os: windows
+            flags: /EHsc
+    env:
+      CARGO_TERM_COLOR: always
+      CXXFLAGS: ${{matrix.flags}}
+      RUSTFLAGS: --cfg deny_warnings -Dwarnings
+    steps:
+      - uses: actions/checkout@v2
+        with:
+          submodules: recursive
+      - uses: dtolnay/rust-toolchain@master
+        with:
+          toolchain: ${{matrix.rust}}
+          components: rustfmt
+      # For operating systems that have it packaged, install creduce
+      - name: Install creduce (Linux)
+        if: matrix.os == ''
+        run: sudo apt-get install creduce
+      - name: Install creduce (MacOS)
+        if: matrix.os == 'macOS'
+        run: brew install creduce
+      - name: Set LIBCLANG_PATH (Windows)
+        # Windows github action doesn't set the path for clang, so set it
+        # See https://github.com/rust-lang/rust-bindgen/issues/1797
+        if: matrix.os == 'windows'
+        run: echo "LIBCLANG_PATH=$((gcm clang).source -replace "clang.exe")" >> $env:GITHUB_ENV
+      - name: Exclude failing targets and tests
+        # no creduce on Windows, so exclude tests needing creduce there
+        run: |
+          echo RUSTFLAGS=$RUSTFLAGS >> $GITHUB_ENV
+          echo ::set-output name=exclude::${{runner.os == 'Windows' && '--exclude autocxx-reduce --exclude autocxx-gen' || ''}}
+        env:
+          # non-linux failures https://github.com/google/autocxx/issues/819
+          # beta failing tests https://github.com/google/autocxx/issues/818
+          RUSTFLAGS: ${{matrix.name == 'Windows (msvc)' && '--cfg skip_windows_msvc_failing_tests' || ''}} ${{matrix.name == 'Windows (gnu)' && '--cfg skip_windows_gnu_failing_tests' || ''}} ${{matrix.rust == 'beta' && '--cfg skip_beta_failing_tests' || ''}}
+        id: testsuite
+        shell: bash
+      - run: cargo test --workspace ${{steps.testsuite.outputs.exclude}}
+
+  examples:
+    name: ${{matrix.name || format('Rust {0}', matrix.rust)}}-examples
+    runs-on: ${{matrix.os || 'ubuntu'}}-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - rust: nightly
+          - rust: beta
+          - rust: stable
+          - name: macOS
+            rust: nightly
+            os: macos
+          - name: Windows (gnu)
+            rust: nightly-x86_64-pc-windows-gnu
+            os: windows
+          - name: Windows (msvc)
+            rust: nightly-x86_64-pc-windows-msvc
+            os: windows
+            flags: /EHsc
+    env:
+      CARGO_TERM_COLOR: always
+      CXXFLAGS: ${{matrix.flags}}
+      RUSTFLAGS: --cfg deny_warnings -Dwarnings
+    steps:
+      - uses: actions/checkout@v2
+        with:
+          submodules: recursive
+      - uses: dtolnay/rust-toolchain@master
+        with:
+          toolchain: ${{matrix.rust}}
+          components: rustfmt
+      - name: Set LIBCLANG_PATH (Windows)
+        # Windows github action doesn't set the path for clang, so set it
+        # See https://github.com/rust-lang/rust-bindgen/issues/1797
+        if: matrix.os == 'windows'
+        run: echo "LIBCLANG_PATH=$((gcm clang).source -replace "clang.exe")" >> $env:GITHUB_ENV
+      - name: Build s2 example
+        working-directory: ./examples/s2
+        # s2 doesn't link on Windows
+        if: matrix.os != 'windows'
+        run: cargo build
+      - name: Build steam example
+        working-directory: ./examples/steam-mini
+        run: cargo build
+      - name: Build subclass example
+        working-directory: ./examples/subclass
+        run: cargo build
+      - name: Build pod example
+        working-directory: ./examples/pod
+        run: cargo build
+      - name: Build chromium render-frame-host example
+        working-directory: ./examples/chromium-fake-render-frame-host
+        # chromium-fake-render-frame-host doesn't link on Windows
+        if: matrix.os != 'windows'
+        run: cargo build
+      - name: Build non-trivial-type-on-stack example
+        working-directory: ./examples/non-trivial-type-on-stack
+        run: cargo build
+
+  clippy:
+    name: Clippy
+    runs-on: ubuntu-latest
+    env:
+      CARGO_TERM_COLOR: always
+    steps:
+      - uses: actions/checkout@v2
+      - uses: dtolnay/rust-toolchain@clippy
+      - run: cargo clippy --workspace --tests -- -Dclippy::all
+
+  outdated:
+    name: Outdated
+    runs-on: ubuntu-latest
+    env:
+      CARGO_TERM_COLOR: always
+    if: github.event_name != 'pull_request'
+    steps:
+      - uses: actions/checkout@v2
+      - uses: dtolnay/install@cargo-outdated
+      - run: cargo outdated --exit-code 1
diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml
deleted file mode 100644
index b5fd94df..00000000
--- a/.github/workflows/clippy.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-name: Clippy
-on:
-  push:
-    branches: [ main ]
-  pull_request:
-    branches: [ main ]
-jobs:
-  clippy_check:
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@v1
-      - uses: actions-rs/toolchain@v1
-        with:
-            toolchain: nightly
-            components: clippy
-            override: true
-      - uses: actions-rs/clippy-check@v1
-        with:
-          token: ${{ secrets.GITHUB_TOKEN }}
-          args: --all-features --tests
diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml
deleted file mode 100644
index 23f8d51e..00000000
--- a/.github/workflows/examples.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-name: Examples
-
-on:
-  push:
-    branches: [ main ]
-  pull_request:
-    branches: [ main ]
-
-env:
-  CARGO_TERM_COLOR: always
-
-jobs:
-  build:
-
-    runs-on: ubuntu-latest
-
-    steps:
-    - name: Checkout with submodules
-      uses: actions/checkout@v2
-      with:
-        submodules: recursive
-    - name: Build s2 example
-      working-directory: ./examples/s2
-      run: cargo build --all --verbose
-    - name: Build steam example
-      working-directory: ./examples/steam-mini
-      run: cargo build --all --verbose
-    - name: Build subclass example
-      working-directory: ./examples/subclass
-      run: cargo build --all --verbose
-    - name: Build pod example
-      working-directory: ./examples/pod
-      run: cargo build --all --verbose
-    - name: Build chromium render-frame-host example
-      working-directory: ./examples/chromium-fake-render-frame-host
-      run: cargo build --all --verbose
-    - name: Build non-trivial-type-on-stack example
-      working-directory: ./examples/non-trivial-type-on-stack
-      run: cargo build --all --verbose
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
deleted file mode 100644
index 1435c7ab..00000000
--- a/.github/workflows/rust.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-name: Rust
-
-on:
-  push:
-    branches: [ main ]
-  pull_request:
-    branches: [ main ]
-
-env:
-  CARGO_TERM_COLOR: always
-
-jobs:
-  build:
-
-    runs-on: ubuntu-latest
-
-    steps:
-    - uses: actions/checkout@v2
-    - name: Build
-      run: cargo build --all --verbose
-    - name: Install creduce
-      run: sudo apt-get install creduce
-    - name: Run tests
-      run: cargo test --all --verbose
diff --git a/engine/src/parse_file.rs b/engine/src/parse_file.rs
index fd60a2a2..ad75df0e 100644
--- a/engine/src/parse_file.rs
+++ b/engine/src/parse_file.rs
@@ -107,7 +107,7 @@ fn parse_file_contents(source: syn::File, auto_allowlist: bool) -> Result<Parsed
                         .unwrap_or(false) =>
                 {
                     Segment::Autocxx(
-                        crate::IncludeCppEngine::new_from_syn(mac.mac.clone())
+                        crate::IncludeCppEngine::new_from_syn(mac.mac)
                             .map_err(ParseError::AutocxxCodegenError)?,
                     )
                 }
@@ -273,9 +273,7 @@ pub trait CppBuildable {
 impl ParsedFile {
     /// Get all the autocxxes in this parsed file.
     pub fn get_rs_buildables(&self) -> impl Iterator<Item = &IncludeCppEngine> {
-        fn do_get_rs_buildables(
-            segments: &Vec<Segment>,
-        ) -> impl Iterator<Item = &IncludeCppEngine> {
+        fn do_get_rs_buildables(segments: &[Segment]) -> impl Iterator<Item = &IncludeCppEngine> {
             segments
                 .iter()
                 .flat_map(|s| -> Box<dyn Iterator<Item = &IncludeCppEngine>> {
@@ -292,9 +290,7 @@ impl ParsedFile {
 
     /// Get all items which can result in C++ code
     pub fn get_cpp_buildables(&self) -> impl Iterator<Item = &dyn CppBuildable> {
-        fn do_get_cpp_buildables(
-            segments: &Vec<Segment>,
-        ) -> impl Iterator<Item = &dyn CppBuildable> {
+        fn do_get_cpp_buildables(segments: &[Segment]) -> impl Iterator<Item = &dyn CppBuildable> {
             segments
                 .iter()
                 .flat_map(|s| -> Box<dyn Iterator<Item = &dyn CppBuildable>> {
@@ -316,7 +312,7 @@ impl ParsedFile {
 
     fn get_autocxxes_mut(&mut self) -> impl Iterator<Item = &mut IncludeCppEngine> {
         fn do_get_autocxxes_mut(
-            segments: &mut Vec<Segment>,
+            segments: &mut [Segment],
         ) -> impl Iterator<Item = &mut IncludeCppEngine> {
             segments
                 .iter_mut()
@@ -333,7 +329,7 @@ impl ParsedFile {
     }
 
     pub fn include_dirs(&self) -> impl Iterator<Item = &PathBuf> {
-        fn do_get_include_dirs(segments: &Vec<Segment>) -> impl Iterator<Item = &PathBuf> {
+        fn do_get_include_dirs(segments: &[Segment]) -> impl Iterator<Item = &PathBuf> {
             segments
                 .iter()
                 .flat_map(|s| -> Box<dyn Iterator<Item = &PathBuf>> {
diff --git a/examples/chromium-fake-render-frame-host/build.rs b/examples/chromium-fake-render-frame-host/build.rs
index b709bad9..c329fac9 100644
--- a/examples/chromium-fake-render-frame-host/build.rs
+++ b/examples/chromium-fake-render-frame-host/build.rs
@@ -15,7 +15,8 @@
 fn main() {
     let path = std::path::PathBuf::from("src");
     let mut b = autocxx_build::Builder::new("src/main.rs", &[&path]).expect_build();
-    b.flag_if_supported("-std=c++17")
+    b.flag_if_supported("-std=c++17")       // clang
+        .flag_if_supported("/std:c++17")    // msvc
         .file("src/fake-chromium-src.cc")
         .compile("autocxx-fake-render-frame-host-example");
     println!("cargo:rerun-if-changed=src/main.rs");
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index 4690d201..b3bb959f 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -12,9 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#[cfg(test)]
-mod cmd_test;
-
 use autocxx_engine::parse_file;
 use clap::{crate_authors, crate_version, App, Arg, ArgGroup};
 use proc_macro2::TokenStream;
diff --git a/tools/reduce/src/main.rs b/tools/reduce/src/main.rs
index 994ae08a..01c2abb8 100644
--- a/tools/reduce/src/main.rs
+++ b/tools/reduce/src/main.rs
@@ -12,9 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#[cfg(test)]
-mod reduce_test;
-
 use std::{
     fs::File,
     io::Write,
@@ -266,7 +263,7 @@ fn do_run(matches: ArgMatches, tmp_dir: &TempDir) -> Result<(), std::io::Error>
         .unwrap()
         .to_string();
     let gen_cmd = matches.value_of("gen-cmd").unwrap_or(&default_gen_cmd);
-    if Path::new(gen_cmd).exists() == false {
+    if !Path::new(gen_cmd).exists() {
         panic!(
             "autocxx-gen not found in {}. hint: autocxx-reduce --gen-cmd /path/to/autocxx-gen",
             gen_cmd


Test patch:
diff --git a/gen/cmd/src/cmd_test.rs b/gen/cmd/tests/cmd_test.rs
similarity index 96%
rename from gen/cmd/src/cmd_test.rs
rename to gen/cmd/tests/cmd_test.rs
index 83692fa9..a650e512 100644
--- a/gen/cmd/src/cmd_test.rs
+++ b/gen/cmd/tests/cmd_test.rs
@@ -19,6 +19,7 @@ use tempdir::TempDir;
 
 static MAIN_RS: &str = include_str!("../../../demo/src/main.rs");
 static INPUT_H: &str = include_str!("../../../demo/src/input.h");
+static BLANK: &str = "// Blank autocxx placeholder";
 
 #[test]
 fn test_help() -> Result<(), Box<dyn std::error::Error>> {
@@ -158,7 +159,7 @@ fn assert_contentful(outdir: &TempDir, fname: &str) {
         panic!("File {} didn't exist", p.to_string_lossy());
     }
     assert!(
-        p.metadata().unwrap().len() > super::BLANK.len().try_into().unwrap(),
+        p.metadata().unwrap().len() > BLANK.len().try_into().unwrap(),
         "File {} is empty",
         fname
     );
@@ -170,7 +171,7 @@ fn assert_not_contentful(outdir: &TempDir, fname: &str) {
         panic!("File {} didn't exist", p.to_string_lossy());
     }
     assert!(
-        p.metadata().unwrap().len() <= super::BLANK.len().try_into().unwrap(),
+        p.metadata().unwrap().len() <= BLANK.len().try_into().unwrap(),
         "File {} is not empty",
         fname
     );
diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml
index 53cbd70c..0254c97e 100644
--- a/integration-tests/Cargo.toml
+++ b/integration-tests/Cargo.toml
@@ -1,6 +1,7 @@
 [package]
 name = "autocxx-integration-tests"
 version = "0.1.0"
+autotests = false
 edition = "2021"
 
 [dev-dependencies]
@@ -27,3 +28,8 @@ itertools = "0.10"
 version = "1.0.39"
 features = [ "full" ]
 #features = [ "full", "extra-traits" ]
+
+[[test]]
+name = "integration_tests"
+path = "tests/lib.rs"
+harness = true
\ No newline at end of file
diff --git a/integration-tests/src/tests.rs b/integration-tests/tests/integration_test.rs
similarity index 99%
rename from integration-tests/src/tests.rs
rename to integration-tests/tests/integration_test.rs
index e4b532ac..a9d26db1 100644
--- a/integration-tests/src/tests.rs
+++ b/integration-tests/tests/integration_test.rs
@@ -3511,6 +3511,8 @@ fn test_root_ns_meth_ret_nonpod() {
     run_test("", hdr, rs, &["Bob"], &["B::C"]);
 }
 
+#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
+#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
 #[test]
 fn test_forward_declaration() {
     let hdr = indoc! {"
@@ -3558,6 +3560,8 @@ fn test_ulong() {
     run_test("", hdr, rs, &["daft"], &[]);
 }
 
+#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
+#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
 #[test]
 fn test_typedef_to_ulong() {
     let hdr = indoc! {"
@@ -3632,6 +3636,8 @@ fn test_reserved_name() {
     run_test("", hdr, rs, &["async_"], &[]);
 }
 
+#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
+#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
 #[test]
 fn test_nested_type() {
     // Test that we can import APIs that use nested types.
@@ -4461,6 +4467,8 @@ fn test_double_underscores_ignored() {
     run_test("", hdr, rs, &["B"], &[]);
 }
 
+// This test fails on Windows gnu but not on Windows msvc
+#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
 #[test]
 fn test_double_underscore_typedef_ignored() {
     let hdr = indoc! {"
@@ -5343,6 +5351,8 @@ fn test_blocklist_not_overly_broad() {
     run_test("", hdr, rs, &["rust_func", "std_func"], &[]);
 }
 
+#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
+#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
 #[test]
 fn test_stringview() {
     // Test that APIs using std::string_view do not otherwise cause errors.
@@ -5413,6 +5423,7 @@ fn test_include_cpp_in_path() {
     do_run_test_manual("", hdr, rs, None, None).unwrap();
 }
 
+#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
 #[test]
 fn test_bitset() {
     let hdr = indoc! {"
@@ -5915,6 +5926,7 @@ fn test_rust_reference() {
     );
 }
 
+#[cfg_attr(skip_beta_failing_tests, ignore)]
 #[test]
 fn test_rust_reference_autodiscover() {
     let hdr = indoc! {"
@@ -6014,6 +6026,7 @@ fn test_rust_reference_method() {
     );
 }
 
+#[cfg_attr(skip_beta_failing_tests, ignore)]
 #[test]
 fn test_box() {
     let hdr = indoc! {"
@@ -6308,6 +6321,7 @@ fn test_pv_subclass_not_pub() {
     );
 }
 
+#[cfg_attr(skip_beta_failing_tests, ignore)]
 #[test]
 fn test_pv_subclass_ptr_param() {
     let hdr = indoc! {"
@@ -6352,6 +6366,8 @@ fn test_pv_subclass_ptr_param() {
     );
 }
 
+#[cfg_attr(skip_beta_failing_tests, ignore)]
+#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
 #[test]
 fn test_pv_subclass_return() {
     let hdr = indoc! {"
@@ -6393,6 +6409,7 @@ fn test_pv_subclass_return() {
     );
 }
 
+#[cfg_attr(skip_beta_failing_tests, ignore)]
 #[test]
 fn test_pv_subclass_passed_to_fn() {
     let hdr = indoc! {"
@@ -6435,6 +6452,7 @@ fn test_pv_subclass_passed_to_fn() {
     );
 }
 
+#[cfg_attr(skip_beta_failing_tests, ignore)]
 #[test]
 fn test_pv_subclass_derive_defaults() {
     let hdr = indoc! {"
@@ -6564,6 +6582,7 @@ fn test_two_subclasses() {
     );
 }
 
+#[cfg_attr(skip_beta_failing_tests, ignore)]
 #[test]
 fn test_two_superclasses_with_same_name_method() {
     let hdr = indoc! {"
@@ -6660,6 +6679,7 @@ fn test_pv_protected_constructor() {
     );
 }
 
+#[cfg_attr(skip_beta_failing_tests, ignore)]
 #[test]
 fn test_pv_protected_method() {
     let hdr = indoc! {"
@@ -6843,6 +6863,7 @@ fn test_pv_subclass_allocation_not_self_owned() {
     );
 }
 
+#[cfg_attr(skip_beta_failing_tests, ignore)]
 #[test]
 fn test_pv_subclass_allocation_self_owned() {
     let hdr = indoc! {"
@@ -7002,6 +7023,7 @@ fn test_pv_subclass_allocation_self_owned() {
     );
 }
 
+#[cfg_attr(skip_beta_failing_tests, ignore)]
 #[test]
 fn test_pv_subclass_calls() {
     let hdr = indoc! {"
@@ -7207,6 +7229,7 @@ fn test_pv_subclass_calls() {
     );
 }
 
+#[cfg_attr(skip_beta_failing_tests, ignore)]
 #[test]
 fn test_pv_subclass_types() {
     let hdr = indoc! {"
@@ -7517,6 +7540,7 @@ fn test_pv_subclass_overrides() {
     );
 }
 
+#[cfg_attr(skip_beta_failing_tests, ignore)]
 #[test]
 fn test_pv_subclass_namespaced_superclass() {
     let hdr = indoc! {"
@@ -7689,6 +7713,8 @@ fn test_copy_and_move_constructor_moveit() {
     run_test("", hdr, rs, &["A"], &[]);
 }
 
+// This test fails on Windows gnu but not on Windows msvc
+#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
 #[test]
 fn test_uniqueptr_moveit() {
     let hdr = indoc! {"
@@ -7711,6 +7737,8 @@ fn test_uniqueptr_moveit() {
     run_test("", hdr, rs, &["A"], &[]);
 }
 
+// This test fails on Windows gnu but not on Windows msvc
+#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
 #[test]
 fn test_various_emplacement() {
     let hdr = indoc! {"
@@ -7739,6 +7767,7 @@ fn test_various_emplacement() {
     run_test("", hdr, rs, &["A"], &[]);
 }
 
+#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
 #[test]
 fn test_emplace_uses_overridden_new_and_delete() {
     let hdr = indoc! {"
@@ -7913,6 +7942,7 @@ fn test_no_rvo_move() {
     );
 }
 
+#[cfg_attr(skip_beta_failing_tests, ignore)]
 #[test]
 fn test_abstract_up() {
     let hdr = indoc! {"
@@ -7962,6 +7992,7 @@ fn test_class_having_protected_method() {
     run_test("", hdr, rs, &[], &["A"]);
 }
 
+#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
 #[test]
 fn test_protected_inner_class() {
     let hdr = indoc! {"
@@ -7987,6 +8018,7 @@ fn test_protected_inner_class() {
     run_test("", hdr, rs, &["A"], &[]);
 }
 
+#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
 #[test]
 fn test_private_inner_class() {
     let hdr = indoc! {"
@@ -8064,6 +8096,7 @@ fn size_and_alignment_test(pod: bool) {
     "},
         type_definitions, function_definitions
     );
+    #[allow(clippy::unnecessary_to_owned)] // wrongly triggers on into_iter() below
     let allowlist_fns: Vec<String> = TYPES
         .iter()
         .flat_map(|(name, _)| {
diff --git a/integration-tests/src/lib.rs b/integration-tests/tests/lib.rs
similarity index 94%
rename from integration-tests/src/lib.rs
rename to integration-tests/tests/lib.rs
index ada9cf22..c66a9c56 100644
--- a/integration-tests/src/lib.rs
+++ b/integration-tests/tests/lib.rs
@@ -12,8 +12,5 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#[cfg(test)]
-mod tests;
-
-#[cfg(test)]
+mod integration_test;
 mod test_utils;
diff --git a/integration-tests/src/test_utils.rs b/integration-tests/tests/test_utils.rs
similarity index 98%
rename from integration-tests/src/test_utils.rs
rename to integration-tests/tests/test_utils.rs
index 56e57412..dc1a13b8 100644
--- a/integration-tests/src/test_utils.rs
+++ b/integration-tests/tests/test_utils.rs
@@ -12,6 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#![cfg(test)]
+
 use std::{
     fs::File,
     io::{BufRead, BufReader, Read, Write},
@@ -86,7 +88,7 @@ impl LinkableTryBuilder {
         }
         for generated_rs in generated_rs_files {
             self.move_items_into_temp_dir(
-                &generated_rs.parent().unwrap().to_path_buf(),
+                &generated_rs.parent().unwrap(),
                 generated_rs.file_name().unwrap().to_str().unwrap(),
             );
         }
@@ -108,7 +110,7 @@ fn write_to_file(tdir: &TempDir, filename: &str, content: &str) -> PathBuf {
 }
 
 /// A positive test, we expect to pass.
-pub(crate) fn run_test(
+pub fn run_test(
     cxx_code: &str,
     header_code: &str,
     rust_code: TokenStream,
@@ -382,7 +384,8 @@ where
         .host(&target)
         .target(&target)
         .opt_level(1)
-        .flag("-std=c++14");
+        .flag("-std=c++14") // For clang
+        .flag_if_supported("/GX"); // Enable C++ exceptions for msvc
     let b = if let Some(builder_modifier) = builder_modifier {
         builder_modifier.modify_cc_builder(b)
     } else {