Skip to content
This repository was archived by the owner on Mar 7, 2021. It is now read-only.

Commit a67c70c

Browse files
authored
Fixes #34 -- add a test framework (#45)
And some initial tests for printk
1 parent cf3212c commit a67c70c

File tree

6 files changed

+174
-17
lines changed

6 files changed

+174
-17
lines changed

.travis.yml

+3-17
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,15 @@ rust:
55
- nightly
66
cache:
77
- cargo: true
8-
# TODO: dedup this with the MODULE_DIR in env
98
- directories:
10-
- static-filesystem/target/
11-
- hello-world/target/
12-
- example-sysctl/target/
9+
- tests/target/
1310

1411
branches:
1512
only:
1613
- master
1714

18-
matrix:
19-
include:
20-
- env: MODULE_DIR=hello-world MODULE=helloworld
21-
- env: MODULE_DIR=static-filesystem MODULE=staticfilesystem
22-
- env: MODULE_DIR=example-sysctl MODULE=examplesysctl
23-
2415
install:
25-
- sudo apt-get install -y "linux-headers-$(uname -r)"
16+
- sudo apt-get install -y "linux-headers-$(uname -r)" realpath
2617
- type -p cargo-install-update || cargo install --force cargo-update
2718
- |
2819
if type -p cargo-xbuild; then
@@ -33,12 +24,7 @@ install:
3324
- rustup component add rust-src
3425

3526
script:
36-
- cd $MODULE_DIR
37-
- RUST_TARGET_PATH="$(pwd)/.." cargo xbuild --target x86_64-linux-kernel-module
38-
- make
39-
- sudo dmesg -C
40-
- sudo insmod "${MODULE}.ko"
41-
- sudo rmmod "$MODULE"
27+
- ./tests/run_tests.py
4228

4329
after_failure:
4430
- dmesg

tests/Makefile

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
obj-m := testmodule.o
2+
testmodule-objs := $(TEST_LIBRARY)
3+
EXTRA_LDFLAGS += --entry=init_module
4+
5+
all:
6+
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(CURDIR)
7+
8+
clean:
9+
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(CURDIR) clean

tests/printk/Cargo.toml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "printk-tests"
3+
version = "0.1.0"
4+
authors = ["Alex Gaynor <[email protected]>", "Geoffrey Thomas <[email protected]>"]
5+
6+
[lib]
7+
crate-type = ["staticlib"]
8+
9+
[dependencies]
10+
linux-kernel-module = { path = "../.." }

tests/printk/src/lib.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#![no_std]
2+
3+
#[macro_use]
4+
extern crate linux_kernel_module;
5+
6+
struct PrintkTestModule;
7+
8+
impl linux_kernel_module::KernelModule for PrintkTestModule {
9+
fn init() -> linux_kernel_module::KernelResult<Self> {
10+
println!("Single element printk");
11+
println!();
12+
println!("printk with {} parameters{}", 2, "!");
13+
14+
Ok(PrintkTestModule)
15+
}
16+
}
17+
18+
kernel_module!(
19+
PrintkTestModule,
20+
author: "Alex Gaynor and Geoffrey Thomas",
21+
description: "A module for testing println!()",
22+
license: "GPL"
23+
);

tests/printk/tests.rs

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use std::env;
2+
use std::process::Command;
3+
4+
struct LoadedModule {
5+
name: String,
6+
}
7+
8+
impl LoadedModule {
9+
fn load(name: String) -> LoadedModule {
10+
Command::new("sudo")
11+
.arg("insmod")
12+
.arg(&name)
13+
.status()
14+
.unwrap();
15+
return LoadedModule { name };
16+
}
17+
}
18+
19+
impl Drop for LoadedModule {
20+
fn drop(&mut self) {
21+
Command::new("sudo")
22+
.arg("rmmod")
23+
.arg(&self.name)
24+
.status()
25+
.unwrap();
26+
}
27+
}
28+
29+
fn with_kernel_module<F: Fn()>(f: F) {
30+
Command::new("sudo")
31+
.arg("dmesg")
32+
.arg("-C")
33+
.status()
34+
.unwrap();
35+
let _m = LoadedModule::load(env::var("KERNEL_MODULE").unwrap());
36+
f();
37+
}
38+
39+
fn assert_dmesg_contains(msgs: &[&[u8]]) {
40+
let output = Command::new("dmesg").output().unwrap();
41+
let lines = output.stdout.split(|x| *x == b'\n').collect::<Vec<_>>();
42+
let mut lines: &[&[u8]] = &lines;
43+
for msg in msgs {
44+
let pos = lines.iter().position(|l| l.ends_with(msg));
45+
assert!(pos.is_some());
46+
lines = &lines[pos.unwrap()..];
47+
}
48+
}
49+
50+
#[test]
51+
fn test_printk() {
52+
with_kernel_module(|| {
53+
assert_dmesg_contains(&[b"Single element printk", b"", b"printk with 2 parameters!"]);
54+
});
55+
}

tests/run_tests.py

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!/usr/bin/env python
2+
3+
import os
4+
import subprocess
5+
6+
7+
BASE_DIR = os.path.realpath(os.path.dirname(__file__))
8+
9+
10+
def run(*args, **kwargs):
11+
cwd = kwargs.pop("cwd", None)
12+
environ = kwargs.pop("environ", os.environ)
13+
assert not kwargs
14+
15+
print("+ [running] {}".format(list(args)))
16+
subprocess.check_call(list(args), cwd=cwd, env=environ)
17+
18+
19+
def main():
20+
for path in os.listdir(BASE_DIR):
21+
if (
22+
not os.path.isdir(os.path.join(BASE_DIR, path)) or
23+
not os.path.exists(os.path.join(BASE_DIR, path, "tests.rs"))
24+
):
25+
continue
26+
27+
run(
28+
"cargo", "xbuild", "--target", "x86_64-linux-kernel-module",
29+
cwd=os.path.join(BASE_DIR, path),
30+
environ=dict(
31+
os.environ,
32+
RUST_TARGET_PATH=os.path.join(BASE_DIR, os.path.pardir),
33+
CARGO_TARGET_DIR=os.path.relpath(
34+
os.path.join(BASE_DIR, "target"),
35+
os.path.join(BASE_DIR, path)
36+
),
37+
)
38+
)
39+
40+
module = os.path.join(
41+
BASE_DIR,
42+
"target/x86_64-linux-kernel-module/debug/lib{}_tests.a".format(
43+
path
44+
)
45+
)
46+
run(
47+
"make", "-C", BASE_DIR,
48+
"TEST_LIBRARY={}".format(
49+
os.path.join(
50+
"target/x86_64-linux-kernel-module/debug/",
51+
os.path.basename(module)
52+
)
53+
),
54+
)
55+
run(
56+
"rustc",
57+
"--test",
58+
"--out-dir", os.path.join(BASE_DIR, path),
59+
os.path.join(BASE_DIR, path, "tests.rs"),
60+
)
61+
# TODO: qemu
62+
run(
63+
os.path.join(BASE_DIR, path, "tests"),
64+
environ=dict(
65+
os.environ,
66+
KERNEL_MODULE=os.path.join(BASE_DIR, "testmodule.ko")
67+
)
68+
)
69+
70+
71+
72+
if __name__ == "__main__":
73+
main()
74+

0 commit comments

Comments
 (0)