Skip to content

Commit a5fe55f

Browse files
committed
Use compile-fail to ensure the correctness of our type structure
This replaces all "this should fail to compile" comments with an actual test that they fail to compile. I've attempted to specify as much as I think is relevant about the error messages, without too tightly coupling to the exact wording that rustc gives when possible. I might need to be more loose in the future. It's a shame there's no way to specify a regex here, because most of the time what I care about is that it includes the name of a trait that isn't implemented, and the right error code.
1 parent 0561695 commit a5fe55f

9 files changed

Lines changed: 155 additions & 21 deletions

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ authors = ["Sean Griffin <sean@thoughtbot.com>"]
77
libc = "*"
88
pq-sys = "0.1.*"
99
byteorder = "0.3.*"
10+
11+
[dev-dependencies]
12+
compiletest_rs = "*"

src/tests/find.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ fn find() {
1313
assert_eq!(Ok(Some(User::new(1, "Sean"))), connection.find(&users, &1));
1414
assert_eq!(Ok(Some(User::new(2, "Tess"))), connection.find(&users, &2));
1515
assert_eq!(Ok(None::<User>), connection.find(&users, &3));
16-
// This should fail type checking, and we should add a test to ensure
17-
// it continues to fail to compile.
18-
// connection.find(&users, &"1").unwrap();
1916
}
2017

2118
table! {
@@ -37,8 +34,4 @@ fn find_with_non_serial_pk() {
3734
assert_eq!(Ok(Some("Sean".to_string())), connection.find(&users, &"Sean"));
3835
assert_eq!(Ok(Some("Tess".to_string())), connection.find(&users, &"Tess".to_string()));
3936
assert_eq!(Ok(None::<String>), connection.find(&users, &"Wibble"));
40-
// This should fail type checking, and we should add a test to ensure
41-
// it continues to fail to compile.
42-
// connection.find(&users, &1).unwrap();
4337
}
44-

src/tests/select.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,11 @@ fn with_safe_select() {
4444
.unwrap();
4545

4646
let select_id = users.select(id);
47-
// This should fail type checking, and we should add a test to ensure
48-
// it continues to fail to compile.
49-
// let select_id = users.select(posts::id);
5047
let select_name = users.select(name);
5148
let ids: Vec<_> = connection.query_all(&select_id)
5249
.unwrap().collect();
5350
let names: Vec<String> = connection.query_all(&select_name)
5451
.unwrap().collect();
55-
// This should fail type checking, and we should add a test to ensure
56-
// it continues to fail to compile.
57-
// let names: Vec<String> = connection.query_all(&select_id)
58-
// .unwrap().collect();
5952

6053
assert_eq!(vec![1, 2], ids);
6154
assert_eq!(vec!["Sean".to_string(), "Tess".to_string()], names);
@@ -72,10 +65,6 @@ fn selecting_multiple_columns() {
7265
.unwrap();
7366

7467
let source = users.select((name, hair_color));
75-
// This should fail type checking, and we should add a test to ensure
76-
// it continues to fail to compile.
77-
// let source = users.select((posts::title, posts::user_id));
78-
// let source = users.select((posts::title, name));
7968
let expected_data = vec![
8069
("Jim".to_string(), Some("Black".to_string())),
8170
("Bob".to_string(), Some("Brown".to_string())),
@@ -116,9 +105,6 @@ fn with_select_sql() {
116105

117106
let select_count = users::table.select_sql::<types::BigInt>("COUNT(*)");
118107
let get_count = || connection.query_one::<_, i64>(&select_count).unwrap();
119-
// This should fail type checking, and we should add a test to ensure
120-
// it continues to fail to compile.
121-
// let actual_count = connection.query_one::<_, String>(&select_count).unwrap();
122108

123109
assert_eq!(Some(2), get_count());
124110

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#[macro_use]
2+
extern crate yaqb;
3+
4+
use yaqb::*;
5+
6+
table! {
7+
int_primary_key {
8+
id -> Serial,
9+
}
10+
}
11+
12+
table! {
13+
string_primary_key {
14+
id -> VarChar,
15+
}
16+
}
17+
18+
fn main() {
19+
let connection = Connection::establish("").unwrap();
20+
let one = connection.find(&int_primary_key::table, &"1").unwrap();
21+
//~^ ERROR the trait `yaqb::types::ToSql<yaqb::types::Serial>` is not implemented
22+
let string = connection.find(&string_primary_key::table, &1).unwrap();
23+
//~^ ERROR the trait `yaqb::types::ToSql<yaqb::types::VarChar>` is not implemented
24+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#[macro_use]
2+
extern crate yaqb;
3+
4+
use yaqb::*;
5+
6+
table! {
7+
users {
8+
id -> Serial,
9+
name -> VarChar,
10+
}
11+
}
12+
13+
fn main() {
14+
use self::users::columns::*;
15+
use self::users::table as users;
16+
17+
let connection = Connection::establish("").unwrap();
18+
let select_id = users.select(id);
19+
let select_name = users.select(name);
20+
21+
let ids: Vec<i32> = connection.query_all(&select_name).unwrap().collect();
22+
//~^ ERROR the trait `yaqb::query_source::Queriable<yaqb::types::VarChar>` is not implemented for the type `i32`
23+
//~| ERROR E0277
24+
//~| ERROR E0277
25+
//~| ERROR E0277
26+
let names: Vec<String> = connection.query_all(&select_id).unwrap().collect();
27+
//~^ ERROR the trait `yaqb::query_source::Queriable<yaqb::types::Serial>` is not implemented
28+
//~| ERROR E0277
29+
//~| ERROR E0277
30+
//~| ERROR E0277
31+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#[macro_use]
2+
extern crate yaqb;
3+
4+
use yaqb::*;
5+
6+
table! {
7+
users {
8+
id -> Serial,
9+
name -> VarChar,
10+
}
11+
}
12+
13+
table! {
14+
posts {
15+
id -> Serial,
16+
title -> VarChar,
17+
}
18+
}
19+
20+
fn main() {
21+
let connection = Connection::establish("").unwrap();
22+
let select_id = users::table.select(posts::id);
23+
//~^ ERROR SelectableColumn
24+
let select_id = users::table.select(posts::id);
25+
//~^ ERROR E0277
26+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#[macro_use]
2+
extern crate yaqb;
3+
4+
use yaqb::*;
5+
6+
table! {
7+
users {
8+
id -> Serial,
9+
name -> VarChar,
10+
}
11+
}
12+
13+
fn main() {
14+
let connection = Connection::establish("").unwrap();
15+
let select_count = users::table.select_sql::<types::BigInt>("COUNT(*)");
16+
let count = connection.query_one::<_, String>(&select_count).unwrap();
17+
//~^ ERROR type mismatch
18+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#[macro_use]
2+
extern crate yaqb;
3+
4+
use yaqb::*;
5+
6+
table! {
7+
users {
8+
id -> Serial,
9+
name -> VarChar,
10+
}
11+
}
12+
13+
table! {
14+
posts {
15+
id -> Serial,
16+
title -> VarChar,
17+
user_id -> Integer,
18+
}
19+
}
20+
21+
fn main() {
22+
let connection = Connection::establish("").unwrap();
23+
let stuff = users::table.select((posts::id, posts::user_id));
24+
//~^ ERROR SelectableColumn
25+
//~| ERROR E0277
26+
let stuff = users::table.select((posts::id, users::name));
27+
//~^ ERROR E0277
28+
}

tests/compile_tests.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
extern crate compiletest_rs as compiletest;
2+
3+
use std::path::PathBuf;
4+
use std::env::var;
5+
6+
fn run_mode(mode: &'static str) {
7+
let mut config = compiletest::default_config();
8+
9+
let cfg_mode = mode.parse().ok().expect("Invalid mode");
10+
11+
config.target_rustcflags = Some("-L target/debug/ -L target/debug/deps/".to_owned());
12+
if let Ok(name) = var::<&str>("TESTNAME") {
13+
let s : String = name.to_owned();
14+
config.filter = Some(s)
15+
}
16+
config.mode = cfg_mode;
17+
config.src_base = PathBuf::from(format!("tests/{}", mode));
18+
19+
compiletest::run_tests(&config);
20+
}
21+
22+
#[test]
23+
fn compile_test() {
24+
run_mode("compile-fail");
25+
}

0 commit comments

Comments
 (0)