pgrx icon indicating copy to clipboard operation
pgrx copied to clipboard

Cannot use non-inline modules in a proc macro (second attempt to move tests to separate file)

Open theory opened this issue 1 year ago • 5 comments

In follow-up to #1631, I followed the second example in this Discord post, setting up the test module like so:

#[cfg(test)]
#[path = "./tests.rs"]
mod test;

And the contents of tests.rs are:

#![pg_schema]
use pgrx::prelude::*;

#[pg_test]
fn test_hello_separate_tests() {
    assert_eq!("Hello, separate_tests", crate::hello_separate_tests());
}

/// This module is required by `cargo pgrx test` invocations.
/// It must be visible at the root of your extension crate.
#[cfg(test)]
pub mod pg_test {
    pub fn setup(_options: Vec<&str>) {
        // perform one-off initialization when the pg_test framework starts
    }

    pub fn postgresql_conf_options() -> Vec<&'static str> {
        // return any postgresql.conf settings that are required for your tests
        vec![]
    }
}

But the compiler complains:

error[E0658]: non-inline modules in proc macro input are unstable
  --> src/lib.rs:12:1
   |
12 | mod tests;
   | ^^^^^^^^^^
   |
   = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information

error: custom attribute panicked
  --> src/lib.rs:11:1
   |
11 | #[pg_schema]
   | ^^^^^^^^^^^^
   |
   = help: message: Can only support `mod {}` right now.

For more information about this error, try `rustc --explain E0658`.
error: could not compile `separate_tests` (lib test) due to 2 previous errors

The errors go away if I remove #![pg_schema] and change the test_hello_separate_tests from #[pg_test] to #[test].

theory avatar Apr 03 '24 14:04 theory

This almost works for the contents of tests.rs:

use pgrx::prelude::*;

#[cfg(any(test, feature = "pg_test"))]
#[pg_schema]
mod gotest {

    #[pg_test]
    fn test_hello_separate_tests() {
        assert_eq!("Hello, separate_tests", crate::hello_separate_tests());
    }
}

/// This module is required by `cargo pgrx test` invocations.
/// It must be visible at the root of your extension crate.
#[cfg(test)]
pub mod pg_test {
    pub fn setup(_options: Vec<&str>) {
        // perform one-off initialization when the pg_test framework starts
    }

    pub fn postgresql_conf_options() -> Vec<&'static str> {
        // return any postgresql.conf settings that are required for your tests
        vec![]
    }
}

The only error is from #[pg_test] over the test function:

cannot find attribute `pg_test` in this scope

It works if I use #[test] instead; maybe I need to qualify the name somehow?

theory avatar Apr 03 '24 14:04 theory

In follow-up to #1631, I followed the second example in this Discord post, setting up the test module like so:

#[cfg(test)]
#[path = "./tests.rs"]
mod test;

Hmm, this should be

#[cfg(test)]
mod tests;

This doesn't matter, however.

Interesting. A comment in the pg_schema macro's entrypoint claims that this usage is blocked on https://github.com/rust-lang/rust/issues/54725 but I don't think so since we pervasively reference module_path. Everything here should work just fine for pg_schema as an inner attribute, it just requires ~~hitting it with a wrench~~ fixing a few codepaths.

It works if I use #[test] instead; maybe I need to qualify the name somehow?

This requires the test module to contain:

mod gotest {
    use super::*;

Because the prelude of pgrx is not automatically visible inside submodules inside a file.

workingjubilee avatar Apr 04 '24 03:04 workingjubilee

Hmm, this should be

#[cfg(test)]
mod tests;

I think it could be if I named the file ./tests/lib.rs or something. But I named it tests.rs so had to tell it where to find the module.

This requires the test module to contain:

mod gotest {
    use super::*;

Because the prelude of pgrx is not automatically visible inside submodules inside a file.

After my original post I got as far as a single issue by adding use super::pg_test;, which achieves the same thing (better to import all tho). It still complains:

error[E0433]: failed to resolve: unresolved import
 --> src/./tests.rs:8:5
  |
8 |     #[pg_test]
  |     ^^^^^^^^^^ unresolved import
  |
  = note: this error originates in the attribute macro `pg_test` (in Nightly builds, run with -Z macro-backtrace for more info)
help: a similar path exists
  |
8 |     crate::tests::pg_test
  |
help: consider importing this module
  |
6 +     use crate::tests::pg_test;
  |

Amusingly I get exactly the same error if I use crate::tests::pg_test;.

theory avatar Apr 15 '24 17:04 theory

I think it could be if I named the file ./tests/lib.rs or something. But I named it tests.rs so had to tell it where to find the module.

That is not the case.

Are you writing this somewhere other than lib.rs? Modules are hierarchical.

You may find reading fasterthanlime's article helpful.

workingjubilee avatar Apr 15 '24 22:04 workingjubilee

I think it could be if I named the file ./tests/lib.rs or something. But I named it tests.rs so had to tell it where to find the module.

That is not the case.

Okay I just removed the #[path = "./tests.rs"] and it's no different. I must have previous had it named mod test or something, hence the confusion.

Are you writing this somewhere other than lib.rs? Modules are hierarchical.

I am not.

You may find reading fasterthanlime's article helpful.

🔖ed!

theory avatar Apr 16 '24 17:04 theory