How to use inline documentation for tests in rust - testing

I am trying to get rust to test an example from my inline documentation. I wrote the following code:
#[derive(Clone)]
#[derive(PartialEq)]
#[derive(Debug)]
enum Color {
Black = 1,
Empty = 0,
White = -1
}
/// Chages Color to the next player
///
/// Returns: White if player is Black, Black if player is White and Empty if
/// player is Empty.
///
/// Examlple
/// ```
/// assert_eq!(flip(&Color::White),Color::Black);
///```
// Invariant Color must represent Black as 1, Empty as 0 and White as -1!
fn flip(player: &Color)->Color{
let intrepresentation :i8 = (player.clone() as i8) * (-1);
unsafe{
std::mem::transmute(intrepresentation)
}
}
fn main() {
assert_eq!(flip(&Color::White),Color::Black);
}
Then I run
rustdoc --test src/main.rs
Which gave me:
running 1 test
test src/main.rs - flip (line 16) ... FAILED
failures:
---- src/main.rs - flip (line 16) stdout ----
error[E0433]: failed to resolve: use of undeclared type or module `Color`
--> src/main.rs:17:18
|
3 | assert_eq!(flip(&Color::White),Color::Black);
| ^^^^^ use of undeclared type or module `Color`
error[E0433]: failed to resolve: use of undeclared type or module `Color`
--> src/main.rs:17:32
|
3 | assert_eq!(flip(&Color::White),Color::Black);
| ^^^^^ use of undeclared type or module `Color`
error[E0425]: cannot find function `flip` in this scope
--> src/main.rs:17:12
|
3 | assert_eq!(flip(&Color::White),Color::Black);
| ^^^^ not found in this scope
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0425, E0433.
For more information about an error, try `rustc --explain E0425`.
Couldn't compile the test.
failures:
src/main.rs - flip (line 16)
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
How can I get rustc to find flip and Color. The test runs fine in the main function. I have also tried the command:
cargo test
but that did not run any tests.
I have tried add the following line to the example:
/// use crate::{flip, Color};
making:
// Chages Color to the next player
///
/// Returns: White if player is Black, Black if player is White and Empty if
/// player is Empty.
///
/// Examlple
/// ```
/// use crate::{flip, Color};
/// assert_eq!(flip(&Color::White),Color::Black);
///```
but that gives an error
martin#martin-laptop:~/test_code$ rustdoc --test src/main.rs
running 1 test
test src/main.rs - main (line 23) ... FAILED
failures:
---- src/main.rs - main (line 23) stdout ----
error[E0432]: unresolved import `crate::Color`
--> src/main.rs:24:14
|
3 | use crate::{ Color};
| ^^^^^ no `Color` in the root
error[E0425]: cannot find function `flip` in this scope
--> src/main.rs:25:12
|
4 | assert_eq!(flip(&Color::White),Color::Black);
| ^^^^ not found in this scope
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0425, E0432.
For more information about an error, try `rustc --explain E0425`.
Couldn't compile the test.
failures:
src/main.rs - main (line 23)
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
I have also tried to Color and flip as public:
#[derive(Clone)]
#[derive(PartialEq)]
#[derive(Debug)]
pub enum Color {
Black = 1,
Empty = 0,
White = -1
}
/// Chages Color to the next player
///
/// Returns: White if player is Black, Black if player is White and Empty if
/// player is Empty.
///
/// Examlple
/// ```
/// use crate::{flip, Color};
/// use std::env;
/// assert_eq!(flip(&Color::White),Color::Black);
///```
// Invariant Color must represent Black as 1, Empty as 0 and White as -1!
pub fn flip(player: &Color)->Color{
let intrepresentation :i8 = (player.clone() as i8) * (-1);
unsafe{
std::mem::transmute(intrepresentation)
}
}
fn main() {
assert_eq!(flip(&Color::White),Color::Black);
}
but that gave the same error.

Doc tests (tests inside /// ```) are compiled separately as tiny programs of their own. Therefore:
They can only access public items: pub mod, pub fn, pub struct, ...
They can only access library crates that export items to be used by other crates — if your program is in main.rs then it's a binary crate.
You have to fully qualify or use the names, like use my_library::Color;.
If you want to test things that don't fit this, then you should use #[test] tests instead:
#[test]
fn flip_test() {
assert_eq!(flip(&Color::White), Color::Black);
}
Any function located anywhere in your program with the attribute #[test] will be run as a test. So, they can access private items since they're in the same module (or a submodule; it's common to put them inside a module named tests in the same file, with mod tests { ... }).
You can find more information about how to write test functions and organize your tests at The Rust Programming Language: How to Write Tests.
I have also tried to Color and flip as public:
/// use crate::{flip, Color};
This doesn't work because crate refers to the current crate, which for a doc test is the test program, not your main crate.

Related

How to include function in documentation test example?

I am trying to make a simple documentation example but it doesn't compile. I tried:
/// Given an axis in 3D returns the indices of the 3 basis axis in the order such
/// that the first index represents forward (the input) the next the side and the final
/// the up. i.e. it computes the even permutation of basis index that creates the
/// rotation that aligns the basis with the selected axis.
///
/// # Arguments
///
/// * index an index from 0-2 selecting the forward axis.
///
/// # Examples
///
/// ```
/// use crate::axis_index_to_basis_indices;
/// let x_index = 0;
/// let y_index = 1;
/// let z_index = 2;
/// let (forward, side, up) = axis_index_to_basis_indices(x_index);
/// assert!(forward == x_index);
/// assert!(side == y_index);
/// assert!(up == z_index);
///
/// let (forward, side, up) = axis_index_to_basis_indices(z_index);
/// assert!(forward == z_index);
/// assert!(side == x_index);
/// assert!(up == y_index);
/// ```
fn axis_index_to_basis_indices(index: i32) -> (i32, i32, i32)
{
match index
{
0 => (0, 1, 2),
1 => (1, 2, 0),
2 => (2, 0, 1),
_ => panic!(),
}
}
Which gives:
error[E0432]: unresolved import `crate::axis_index_to_basis_indices`
--> dual_contouring.rs:107:5
|
3 | use crate::axis_index_to_basis_indices;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `axis_index_to_basis_indices` in the root
error: aborting due to previous error
For more information about this error, try `rustc --explain E0432`.
Couldn't compile the test.
failures:
dual_contouring.rs - axis_index_to_basis_indices (line 106)
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s
error: doctest failed, to rerun pass `--doc`
The official docs are incomplete in this regard. Reading them one would assume the include statement should be use doc::name_of_crate but that also doesn't work.

Change color of mesh displayed by the function CGAL::draw()

Problem descriptionI wonder if there is a way to change the color of mesh displayed by the function CGAL::draw(). I have a Surface_mesh, I want to draw it with CGAL. So I use the function CGAL::draw(), but the color of mesh is blue, which is not pretty in my view. I tried to change the code of CGAL to change the color. I found a functor called DefaultColorFunctorFaceGraph in a header file called draw_face_graoh.h, there is an annotation above the definition of DefaultColorFunctorFaceGraph, which says "// Default color functor; user can change it to have its own face color". I change the functor, in which I change the return value to CGAL::IO::gray(), but it doesn't work at all, the color of mesh is still blue.So can I change the color of mesh by changing the code of CGAL? Is it necessary to change lower level code such as some codes calling OpenGL?
Code
Here is an example about the way I use the function draw().
#include<iostream>
#include<fstream>
#include<CGAL/Surface_mesh.h>
#include<CGAL/draw_surface_mesh.h>
#include<CGAL/Exact_predicates_inexact_constructions_kernel.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel kernel;
typedef kernel::Point_3 point;
typedef CGAL::Surface_mesh<point> Mesh;
int main() {
std::ifstream fin("test.off");
Mesh mesh;
fin >> mesh;
CGAL::draw(mesh);
}
The file called test.off is as follws.
OFF
4 4 0
0 0 1
0 0 0
1 0 0
0 1 0
3 2 0 1
3 1 0 3
3 1 3 2
3 3 0 2
Here is the changed functor.
namespace CGAL
{
// Default color functor; user can change it to have its own face color
struct DefaultColorFunctorFaceGraph
{
template<typename Graph>
CGAL::IO::Color operator()(const Graph&,
typename boost::graph_traits<Graph>::face_descriptor fh) const
{
if (fh == boost::graph_traits<Graph>::null_face()) // use to get the mono color
//return CGAL::IO::Color(100,125,200); // R G B between 0-255
return CGAL::IO::gray();//Here changed
return get_random_color(CGAL::get_default_random());
}
};
Runtime environment
IDE: VS 2017
Solution configuration: Release x64
CGAL version: 5.3
Finally I found a struct named Basic_viewer_qt in a header file called Basic_viewer_qt.h. By changing the values of variables m_faces_mono_color and m_ambient_color in this struct, color of mesh can be changed.

Why Isn't This Module Visible?

I'm coding a hash in Rust for practice. The code looks like this:
pub fn get_fnv1a32(to_hash:&str) -> u32{
const OFFSET_BASIS:u32 = 2_166_136_261;
const PRIME:u32 = 16_777_619;
if !to_hash.is_empty(){
let mut hash = OFFSET_BASIS;
for b in to_hash.bytes(){
hash = hash ^ (b as u32);
hash = hash.wrapping_mul(PRIME);
}
hash
}
else
{
0
}
}
And this is the code I'm trying to use to test this:
mod fnv;
#[cfg(test)]
mod tests {
#[test]
fn get_correct_hash(){
assert_eq!(0x7a78f512, fnv::get_fnv1a32("Hello world!"));
}
#[test]
fn hash_handles_empty_string_correctly(){
assert_eq!(0, fnv::get_fnv1a32(""));
}
}
The test code is in lib.rs and the get_fnv1a32 function is in fnv.rs. They're both in the same directory. But when I try to run cargo test I keep getting these messages:
Compiling hashes v0.1.0 (U:\skunkworks\rust\hashes)
warning: function is never used: `get_fnv1a32`
--> src\fnv.rs:1:8
|
1 | pub fn get_fnv1a32(to_hash:&str) -> u32{
| ^^^^^^^^^^^
|
= note: `#[warn(dead_code)]` on by default
error[E0433]: failed to resolve: use of undeclared type or module `fnv`
--> src\lib.rs:7:32
|
7 | assert_eq!(0x7a78f512, fnv::get_fnv1a32("Hello world!"));
| ^^^ use of undeclared type or module `fnv`
error[E0433]: failed to resolve: use of undeclared type or module `fnv`
--> src\lib.rs:12:23
|
12 | assert_eq!(0, fnv::get_fnv1a32(""));
| ^^^ use of undeclared type or module `fnv`
error: aborting due to 2 previous errors
I can't figure out what I'm doing wrong. I tried changing the mod fnv; line at the top to pub mod fnv; and that gets rid of the dead code warning but it doesn't fix the two errors. What do I need to do to get the get_fnv1a32 function to be visible in the lib.rs file?
Not that I would think it would matter but the version of rustc is rustc 1.41.0 (5e1a79984 2020-01-27)
The test module is separate from the outer module. Add
use super::*;
or an equivalent statement like use crate::fnv inside the tests module to make the fnv module visible.

Xbase Interpreter: Could not access field on instance: null

I am testing the idea of making my dsl Jvm compatible and I wanted to test the possibility of extending Xbase and using the interpreter. I have tried to make a minimal test project to use with the interpreter but I am getting a runtime error. I think I understand the general concepts of adapting Xbase, but am unsure about how the setup/entrypoints for the interpreter and could not find any information regarding the error I am getting or how to resolve. Here are the relevant files for my situation:
Text.xtext:
import "http://www.eclipse.org/xtext/xbase/Xbase" as xbase
import "http://www.eclipse.org/xtext/common/JavaVMTypes" as types
Program returns Program:
{Program}
'program' name=ID '{'
variables=Var_Section?
run=XExpression?
'}'
;
Var_Section returns VarSection:
{VarSection}
'variables' '{'
decls+=XVariableDeclaration+
'}'
;
#Override // Change syntax
XVariableDeclaration returns xbase::XVariableDeclaration:
type=JvmTypeReference name=ID '=' right=XLiteral ';'
;
#Override // Do not allow declarations outside of variable region
XExpressionOrVarDeclaration returns xbase::XExpression:
XExpression;
TestJvmModelInferrer:
def dispatch void infer(Program element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
acceptor.accept(element.toClass(element.fullyQualifiedName)) [
documentation = element.documentation
if (element.variables !== null) {
for (decl : element.variables.decls) {
members += decl.toField(decl.name, decl.type) [
static = true
initializer = decl.right
visibility = JvmVisibility.PUBLIC
]
}
}
if (element.run !== null) {
members += element.run.toMethod('main', typeRef(Void::TYPE)) [
parameters += element.run.toParameter("args", typeRef(String).addArrayTypeDimension)
visibility = JvmVisibility.PUBLIC
static = true
body = element.run
]
}
]
}
Test case:
#Inject ParseHelper<Program> parseHelper
#Inject extension ValidationTestHelper
#Inject XbaseInterpreter interpreter
#Test
def void basicInterpret() {
val result = parseHelper.parse('''
program program1 {
variables {
int var1 = 0;
double var2 = 3.4;
}
var1 = 13
}
''')
result.assertNoErrors
var interpretResult = interpreter.evaluate(result.run)
println(interpretResult.result)
Partial stack trace:
java.lang.IllegalStateException: Could not access field: program1.var1 on instance: null
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._assignValueTo(XbaseInterpreter.java:1262)
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.assignValueTo(XbaseInterpreter.java:1221)
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:1213)
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:216)
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:204)
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:190)
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:180)
The interpreter does only support expressions, but does not work with types that are created by a JvmModelInferrer. Your code tries to work with fields of such an inferred type.
Rather than using the interpreter, I'd recommend to use an InMemoryCompiler in your test. The domainmodel example may serve as an inspiration: https://github.com/eclipse/xtext-eclipse/blob/c2b15c3ec118c4c200e2b28ea72d8c9116fb6800/org.eclipse.xtext.xtext.ui.examples/projects/domainmodel/org.eclipse.xtext.example.domainmodel.tests/xtend-gen/org/eclipse/xtext/example/domainmodel/tests/XbaseIntegrationTest.java
You may find this project interesting, which (among other stuff) implements an interpreter for Xtend based on the Xbase interpreter. It might be a bit outdated, though, and also will not fully support all Xtend concepts. But it could be a starting point, and your contrbutions are welcome :-)
https://github.com/kbirken/xtendency

Tests panic when HTTP server starts after old one is closed

I have some tests written, each function starts iron's HTTP server and closes it after test is done:
extern crate iron;
use iron::prelude::*;
fn hello_world(_: &mut Request) -> IronResult<Response> {
Ok(Response::with((iron::status::Ok, "Hello World")))
}
#[test]
fn test1() {
let mut server = Iron::new(hello_world).http("localhost:3000").unwrap();
server.close().unwrap();
}
#[test]
fn test2() {
let mut server = Iron::new(hello_world).http("localhost:3000").unwrap();
server.close().unwrap();
}
Doing cargo test I'm having:
Running target/debug/lib-f236975fe924352b
running 2 tests
test test1 ... ok
test test2 ... FAILED
failures:
---- test2 stdout ----
thread 'test2' panicked at 'called `Result::unwrap()` on an `Err` value: Io(Error { repr: Os { code: 98, message: "Address already in use" } })', ../src/libcore/result.rs:736
failures:
test2
test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured
It seems like the port is still in use by the start of the second test.
Rust's test runner is parallel by default, so yes, I would expect that this would happen. I would pick a different port number for each test, at least to start, since it's so easy.