How to share a file in test files? [duplicate] - rust

This question already has answers here:
How do I import from a sibling module?
(1 answer)
What is an idiomatic way to have shared utility functions for integration tests and benchmarks?
(3 answers)
Closed 8 months ago.
I have this hierarchy in my substrate pallet:
src/
├── lib.rs
├── mock.rs
├── tests.rs
└── common.rs
Cargo.toml
My mock.rs and tests.rs need to share some constants and types, so I put those into common.rs.
in my mock.rs and tests.rs:
mod common;
use crate::common::{
TOKEN_TRANSFER_FEE, Balance,
};
in my common.rs:
pub mod common {
pub type Balance = u128;
pub const TOKEN_TRANSFER_FEE: Balance = 1_000;
}
then I got these errors:
error[E0583]: file not found for module `common`
--> pallets/bridge/src/mock.rs:48:1
|
48 | mod common;
| ^^^^^^^^^^^
|
= help: to create the module `common`, create file "pallets/bridge/src/mock/common.rs" or "pallets/bridge/src/mock/common/mod.rs"
error[E0583]: file not found for module `common`
--> pallets/bridge/src/tests.rs:36:1
|
36 | mod common;
| ^^^^^^^^^^^
|
= help: to create the module `common`, create file "pallets/bridge/src/tests/common.rs" or "pallets/bridge/src/tests/common/mod.rs"
Is there an easier way to import those constants and types from that shared common file into mock.rs and tests.rs, instead of making mock folder and tests folders?

Use only mod once and in the other files use:
lib
mod common;
mod mock;
fn entry() {
eprintln!("{}", common::common::TEST);
}
common
pub mod common {
pub const TEST: &str = "";
}
mock
use crate::common;
fn mock() {
eprintln!("{}", common::common::TEST);
}

Related

How to use multiple files in rust?

How to use multiple files in rust?
My main code is in file1.rs. file2.rs runs the main function of file1.rs multiple times, that's why I want to split it into 2 files, to keep my code clean. Than I just want to run the main function of file2.rs in my main.rs file. (I'm using the latest version of rust - 2021)
Folder structure:
├── Cargo.lock
├── Cargo.toml
├── src
│ ├── main.rs
│ └── file1.rs
| └── file2.rs
└── target
main.rs
pub mod file1;
pub mod file2;
pub fn main() {
file2::main();
}
file2.rs
pub mod file1;
pub fn main() {
file1::func("Bob");
file1::func("Alice");
}
file1.rs
pub fn func(name: &str) {
println!("Hello {}", name.to_string());
}
I get this error message:
file not found for module `file1`
to create the module `file1`, create file "src/file2/file1.rs"
or "src/file2/file1/mod.rs" rustcE0583
Here you are saying that file2.rs has a module called file1, so your tree should be:
src
|
---- main.rs
---- file2.rs
---- file2
|
----- file1.rs
Or change it to:
main.rs:
pub mod file1;
pub mod file2;
// ...
file2.rs:
// pub mod file1
// ...
You need to make the main functions public using pub fn main() {...}. Also, the syntax you used to call the file1::main is invalid, you would have to provide actual values like 1 and "foo".
You can import from other modules (files) in the same directory:
use super::file2::*;

how to include a module from another file [duplicate]

This question already has answers here:
How can I include a module from another file from the same project?
(6 answers)
Closed 1 year ago.
I created a Cargo project. My project tree looks like this:
├── src
├── main.rs
├── animal.rs
└── human.rs
animal.rs
use crate::human::Job;
pub struct Animal {
id: u8,
job: Job,
}
impl Animal {
pub fn new(i: u8, j: Job) -> Animal {
Animal {id:i, job:j}
}
}
human.rs
pub struct Human {
id: u8,
job: Job,
}
pub enum Job {
Builder,
Magician,
}
impl Human {
pub fn new(i: u8, j: Job) -> Human {
Human {id: i, job: j}
}
}
When I compile it, it complains
$ cargo run
error[E0433]: failed to resolve: could not find `human` in the crate root
--> src/animal.rs:4:17
|
4 | job: crate::human::Job,
| ^^^^^ could not find `human` in the crate root
It gets compiled if I add "mod human;" in main.rs. What is the right way to include one module from another file in the same project?
The default package structure cargo expects is described here: https://doc.rust-lang.org/cargo/guide/project-layout.html
Therefore, you would expect to have the following files:
└── src
├── main.rs
├── lib.rs
├── animal.rs
└── human.rs
And lib.rs should contain
mod animal;
mod human;
The main.rs is an executable that would use the crate as if the library was a dependency:
use <crate_name>::human::Job;
fn main() {
// do whatever with `Job`
}
crate_name here would be the name of the crate in Cargo.toml.
Although technically nothing prevents you from declaring the modules inside main.rs like so:
mod animal;
mod human;
fn main() {
// use `human::Job`
}

Confused on how to use rust modules [duplicate]

This question already has answers here:
Split a module across several files
(7 answers)
How can I include a module from another file from the same project?
(6 answers)
How to use one module from another module in a Rust cargo project?
(3 answers)
Closed 2 years ago.
I have three files. main.rs, foo.rs, bar.rs all in the src directory. I want to use whats in foo.rs in bar.rs. So i have mod foo; inside of bar. But i get an error as shown below. I do not want to put the foo.rs in a sub directory e.g. src/bar/foo.rs is there another way to structure the code? Because i want foo.rs to be used in many different places besides bar.rs. Optionally if you could tell me how you structure a big project with multiple files then that will suffice.
file not found for module `foo`
--> src/bar.rs:1:1
|
1 | mod foo;
| ^^^^^^^^
|
= help: to create the module `foo`, create file "src/bar/foo.rs"
error: aborting due to previous error
main.rs
mod bar;
fn main() {
println!("Hello, world!");
}
foo.rs
pub fn do_something() {
}
bar.rs
mod foo;
You only have to declare modules once, and in this case you would declare both in main and then you would be able to import them from anywhere else in your codebase using use crate::{mod_name}. Example:
src/main.rs
// declare foo & bar modules
mod foo;
mod bar;
fn main() {
foo::foo();
foo::call_bar();
bar::bar();
bar::call_foo();
}
src/foo.rs
// import bar module
use crate::bar;
pub fn foo() {
println!("foo");
}
pub fn call_bar() {
bar::bar();
}
src/bar.rs
// import foo module
use crate::foo;
pub fn bar() {
println!("bar");
}
pub fn call_foo() {
foo::foo();
}

How do I use structs declared in other modules in main.rs? [duplicate]

This question already has answers here:
Rust modules confusion when there is main.rs and lib.rs
(4 answers)
Split a module across several files
(7 answers)
How do I import from a sibling module?
(1 answer)
Closed 2 years ago.
Here is the situation. I have a project named project_name and it has this file hierarchy:
project_name
|-- src
| |-- main.rs
| |-- lib.rs
| `-- tree_node.rs
I declared struct TreeNode in tree_node.rs.
pub struct TreeNode { ... }
There is method using TreeNode in lib.rs:
mod tree_node;
use tree_node::TreeNode;
pub struct Solution {}
impl Solution {
pub fn invert_tree(root: TreeNode) -> TreeNode { ... }
}
But when I try to use method invert_tree in main.rs like this:
use project_name::Solution;
use tree_node::TreeNode;
mod tree_node;
fn main() {
let tree = TreeNode::new(1);
let result = Solution::invert_tree(tree);
}
I got an error:
expected struct `project_name::tree_node::TreeNode`, found struct
`tree_node::TreeNode`
Maybe I use incorrectly term method but I hope the main point is clear. What is wrong?
main.rs and lib.rs are effectively different crates that are compiled separately, and so mod creates separate modules for each when using in both lib and main. Generally you want to only use mod in lib.rs unless some module is only for private use of the application.
Therefore, replace mod tree_node from main.rs with use project_name::tree_node::TreeNode;.
In lib.rs you must change mod tree_node to pub mod tree_node, or pub(crate) mod tree_node if it's only intended for this crate and not outside users.

Cannot import a module in an integration test

I am trying to configure an example project in Rust to work.
My structure is:
src/potter.rs
tests/tests.rs
And my Cargo.toml
[package]
name = "potter"
version = "0.1.0"
authors = ["my name"]
[dependencies]
My potter.rs contains:
pub mod potter {
pub struct Potter {
}
impl Potter {
pub fn new() -> Potter {
return Potter {};
}
}
}
And my tests.rs contains:
use potter::Potter;
#[test]
fn it_works() {
let pot = potter::Potter::new();
assert_eq!(2 + 2, 4);
}
But I receive this error:
error[E0432]: unresolved import `potter`
--> tests/tests.rs:1:5
|
1 | use potter::Potter;
| ^^^^^^ Maybe a missing `extern crate potter;`?
error[E0433]: failed to resolve. Use of undeclared type or module `potter`
--> tests/tests.rs:6:19
|
6 | let pot = potter::Potter::new();
| ^^^^^^ Use of undeclared type or module `potter`
warning: unused import: `potter::Potter`
--> tests/tests.rs:1:5
|
1 | use potter::Potter;
| ^^^^^^^^^^^^^^
|
= note: #[warn(unused_imports)] on by default
If I add extern crate potter;, it doesn't fix anything...
error[E0463]: can't find crate for `potter`
--> tests/tests.rs:1:1
|
1 | extern crate potter;
| ^^^^^^^^^^^^^^^^^^^^ can't find crate
Go back and reread The Rust Programming Language about packages, crates, modules and the filesystem.
Common pain points:
Every programming language has its own way of dealing with files — you cannot just assume that because you've used any other language that you will magically get Rust's take on it. That's why you should go back and re-read the book chapter on it.
Each file defines a module. Your lib.rs defines a module of the same name as your crate; a mod.rs defines a module of the same name as the directory it's in; every other file defines a module of the name of the file.
The root of your library crate must be lib.rs; binary crates may use main.rs.
No, you really shouldn't try to do non-idiomatic filesystem organization. There are tricks to do most anything you want; these are terrible ideas unless you are already an advanced Rust user.
Idiomatic Rust does not generally place "one type per file" like many other languages. Yes, really. You can have multiple things in one file.
Unit tests usually live in the same file as the code it's testing. Sometimes they will be split out into a file containing the submodule, but that's uncommon.
Integration tests, examples, benchmarks all have to import the crate like any other user of the crate and can only use the public API.
To fix your issue:
Move your src/potter.rs to src/lib.rs.
Remove pub mod potter from src/lib.rs. Not strictly required, but removes needless nesting of modules.
Add extern crate potter to your integration test tests/tests.rs (Only needed if you are using Rust 2015).
filesystem
├── Cargo.lock
├── Cargo.toml
├── src
│   └── lib.rs
├── target
└── tests
└── tests.rs
src/lib.rs
pub struct Potter {}
impl Potter {
pub fn new() -> Potter {
Potter {}
}
}
tests/tests.rs
use potter::Potter;
#[test]
fn it_works() {
let pot = Potter::new();
assert_eq!(2 + 2, 4);
}

Resources