Add a new run-make test directory

This infrastructure is meant to support runnings tests that involve various
interesting interdependencies about the types of crates being linked or possibly
interacting with C libraries. The goal of these make tests is to not restrict
them to a particular test runner, but allow each test to run its own tests.

To this end, there is a new src/test/run-make directory which has sub-folders of
tests. Each test requires a `Makefile`, and running the tests constitues simply
running `make` inside the directory. The new target is `check-stageN-rmake`.

These tests will have the destination directory (as TMPDIR) and the local rust
compiler (as RUSTC) passed along to them. There is also some helpful
cross-platform utilities included in src/test/run-make/tools.mk to aid with
compiling C programs and running them.

The impetus for adding this new test suite is to allow various interesting forms
of testing rust linkage. All of the tests initially added are various flavors of
compiling Rust and C with one another as well as just making sure that rust
linkage works in general.

Closes #10434
This commit is contained in:
Alex Crichton 2013-11-16 17:07:32 -08:00
parent 9fbba7b2ee
commit 6d6ccb75ff
58 changed files with 433 additions and 2 deletions

View File

@ -193,7 +193,7 @@ check-lite: cleantestlibs cleantmptestlogs \
check-stage2-std check-stage2-extra check-stage2-rpass \
check-stage2-rustuv \
check-stage2-rustpkg \
check-stage2-rfail check-stage2-cfail
check-stage2-rfail check-stage2-cfail check-stage2-rmake
$(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
.PHONY: cleantmptestlogs cleantestlibs
@ -284,7 +284,8 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \
check-stage$(1)-T-$(2)-H-$(3)-rfail-exec \
check-stage$(1)-T-$(2)-H-$(3)-cfail-exec \
check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \
check-stage$(1)-T-$(2)-H-$(3)-crates-exec \
check-stage$(1)-T-$(2)-H-$(3)-rmake-exec \
check-stage$(1)-T-$(2)-H-$(3)-crates-exec \
check-stage$(1)-T-$(2)-H-$(3)-bench-exec \
check-stage$(1)-T-$(2)-H-$(3)-debuginfo-exec \
check-stage$(1)-T-$(2)-H-$(3)-codegen-exec \
@ -770,6 +771,7 @@ TEST_GROUPS = \
cfail \
bench \
perf \
rmake \
debuginfo \
codegen \
doc \
@ -900,3 +902,36 @@ endef
$(foreach host,$(CFG_HOST), \
$(eval $(call DEF_CHECK_FAST_FOR_H,$(host))))
RMAKE_TESTS := $(shell ls -d $(S)src/test/run-make/*/)
RMAKE_TESTS := $(RMAKE_TESTS:$(S)src/test/run-make/%/=%)
define DEF_RMAKE_FOR_T_H
# $(1) the stage
# $(2) target triple
# $(3) host triple
check-stage$(1)-T-$(2)-H-$(3)-rmake-exec: \
$$(call TEST_OK_FILE,$(1),$(2),$(3),rmake)
$$(call TEST_OK_FILE,$(1),$(2),$(3),rmake): \
$$(RMAKE_TESTS:%=$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok)
@touch $$@
$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
$(S)src/test/run-make/%/Makefile \
$$(HBIN$(1)_H_$(3))/rustc$$(X_$(3))
@rm -rf $(3)/test/run-make/$$*
@mkdir -p $(3)/test/run-make/$$*
@echo maketest: $$*
@python $(S)src/etc/maketest.py $$(dir $$<) \
$$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \
$(3)/test/run-make/$$*
@touch $$@
endef
$(foreach stage,$(STAGES), \
$(foreach target,$(CFG_TARGET), \
$(foreach host,$(CFG_HOST), \
$(eval $(call DEF_RMAKE_FOR_T_H,$(stage),$(target),$(host))))))

26
src/etc/maketest.py Normal file
View File

@ -0,0 +1,26 @@
# xfail-license
import subprocess
import os
import sys
os.putenv('RUSTC', os.path.abspath(sys.argv[2]))
os.putenv('TMPDIR', os.path.abspath(sys.argv[3]))
proc = subprocess.Popen(['make', '-C', sys.argv[1]],
stdout = subprocess.PIPE,
stderr = subprocess.PIPE)
out, err = proc.communicate()
i = proc.wait()
if i != 0:
print '----- ' + sys.argv[1] + """ --------------------
------ stdout ---------------------------------------------
""" + out + """
------ stderr ---------------------------------------------
""" + err + """
------ ---------------------------------------------
"""
sys.exit(i)

View File

@ -0,0 +1,14 @@
-include ../tools.mk
# This hits an assertion in the linker on older versions of osx apparently
ifeq ($(shell uname),Darwin)
all:
echo ignored
else
all: $(call DYLIB,cfoo)
$(RUSTC) foo.rs
$(RUSTC) bar.rs
$(call RUN,bar)
rm $(TMPDIR)/$(call DYLIB_GLOB,cfoo)
$(call FAIL,bar)
endif

View File

@ -0,0 +1,5 @@
extern mod foo;
fn main() {
foo::rsfoo();
}

View File

@ -0,0 +1 @@
int foo() { return 0; }

View File

@ -0,0 +1,10 @@
#[crate_type = "dylib"];
#[link(name = "cfoo")]
extern {
fn foo();
}
pub fn rsfoo() {
unsafe { foo() }
}

View File

@ -0,0 +1,14 @@
-include ../tools.mk
# This hits an assertion in the linker on older versions of osx apparently
ifeq ($(shell uname),Darwin)
all:
echo ignored
else
all: $(call DYLIB,cfoo)
$(RUSTC) foo.rs
$(RUSTC) bar.rs
LD_LIBRARY_PATH=$(TMPDIR) $(call RUN,bar)
rm $(TMPDIR)/$(call DYLIB_GLOB,cfoo)
$(call FAIL,bar)
endif

View File

@ -0,0 +1,5 @@
extern mod foo;
fn main() {
foo::rsfoo();
}

View File

@ -0,0 +1 @@
int foo() { return 0; }

View File

@ -0,0 +1,10 @@
#[crate_type = "rlib"];
#[link(name = "cfoo")]
extern {
fn foo();
}
pub fn rsfoo() {
unsafe { foo() }
}

View File

@ -0,0 +1,9 @@
-include ../tools.mk
all:
$(RUSTC) foo.rs
ln -s $(call DYLIB,foo-*) $(call DYLIB,foo)
$(CC) bar.c -lfoo -o $(call RUN,bar) -Wl,-rpath,$(TMPDIR)
$(call RUN,bar)
rm $(call DYLIB,foo)
$(call FAIL,bar)

View File

@ -0,0 +1,6 @@
void foo();
int main() {
foo();
return 0;
}

View File

@ -0,0 +1,4 @@
#[crate_type = "dylib"];
#[no_mangle]
pub extern "C" fn foo() {}

View File

@ -0,0 +1,13 @@
-include ../tools.mk
ifneq ($(shell uname),Darwin)
EXTRAFLAGS := -lm -lrt -ldl -lpthread
endif
all:
$(RUSTC) foo.rs -Z gen-crate-map
ln -s $(call STATICLIB,foo-*) $(call STATICLIB,foo)
$(CC) bar.c -lfoo -o $(call RUN,bar) $(EXTRAFLAGS) -lstdc++
$(call RUN,bar)
rm $(call STATICLIB,foo*)
$(call RUN,bar)

View File

@ -0,0 +1,6 @@
void foo();
int main() {
foo();
return 0;
}

View File

@ -0,0 +1,4 @@
#[crate_type = "staticlib"];
#[no_mangle]
pub extern "C" fn foo() {}

View File

@ -0,0 +1,9 @@
-include ../tools.mk
all: $(call STATICLIB,cfoo)
$(RUSTC) foo.rs
$(RUSTC) bar.rs
rm $(TMPDIR)/$(call STATICLIB_GLOB,cfoo)
$(call RUN,bar)
rm $(TMPDIR)/$(call DYLIB_GLOB,foo)
$(call FAIL,bar)

View File

@ -0,0 +1,5 @@
extern mod foo;
fn main() {
foo::rsfoo();
}

View File

@ -0,0 +1 @@
int foo() { return 0; }

View File

@ -0,0 +1,10 @@
#[crate_type = "dylib"];
#[link(name = "cfoo")]
extern {
fn foo();
}
pub fn rsfoo() {
unsafe { foo() }
}

View File

@ -0,0 +1,8 @@
-include ../tools.mk
all: $(call STATICLIB,cfoo)
$(RUSTC) foo.rs
$(RUSTC) bar.rs
rm $(TMPDIR)/$(call RLIB_GLOB,foo)
rm $(TMPDIR)/$(call STATICLIB_GLOB,cfoo)
$(call RUN,bar)

View File

@ -0,0 +1,5 @@
extern mod foo;
fn main() {
foo::rsfoo();
}

View File

@ -0,0 +1 @@
int foo() { return 0; }

View File

@ -0,0 +1,10 @@
#[crate_type = "rlib"];
#[link(name = "cfoo")]
extern {
fn foo();
}
pub fn rsfoo() {
unsafe { foo() }
}

View File

@ -0,0 +1,12 @@
-include ../tools.mk
all:
$(RUSTC) m1.rs
$(RUSTC) m2.rs
$(RUSTC) m3.rs
$(RUSTC) m4.rs
$(call RUN,m4)
rm $(TMPDIR)/$(call DYLIB_GLOB,m1)
rm $(TMPDIR)/$(call DYLIB_GLOB,m2)
rm $(TMPDIR)/$(call DYLIB_GLOB,m3)
$(call FAIL,m4)

View File

@ -0,0 +1,2 @@
#[crate_type = "dylib"];
pub fn m1() {}

View File

@ -0,0 +1,4 @@
#[crate_type = "dylib"];
extern mod m1;
pub fn m2() { m1::m1() }

View File

@ -0,0 +1,4 @@
#[crate_type = "dylib"];
extern mod m2;
pub fn m3() { m2::m2() }

View File

@ -0,0 +1,3 @@
extern mod m3;
fn main() { m3::m3() }

View File

@ -0,0 +1,7 @@
-include ../tools.mk
all:
$(RUSTC) both.rs
$(RUSTC) dylib.rs -Z prefer-dynamic
$(RUSTC) prog.rs
$(call RUN,prog)

View File

@ -0,0 +1,4 @@
#[crate_type = "rlib"];
#[crate_type = "dylib"];
pub static foo: int = 4;

View File

@ -0,0 +1,6 @@
#[crate_type = "dylib"];
extern mod both;
use std::cast;
pub fn addr() -> uint { unsafe { cast::transmute(&both::foo) } }

View File

@ -0,0 +1,9 @@
extern mod dylib;
extern mod both;
use std::cast;
fn main() {
assert_eq!(unsafe { cast::transmute::<&int, uint>(&both::foo) },
dylib::addr());
}

View File

@ -0,0 +1,9 @@
-include ../tools.mk
all:
$(RUSTC) rlib.rs
$(RUSTC) dylib.rs && exit 1 || exit 0
$(RUSTC) rlib.rs --dylib
$(RUSTC) dylib.rs
rm $(call DYLIB,rlib-*)
$(RUSTC) prog.rs && exit 1 || exit 0

View File

@ -0,0 +1,4 @@
#[crate_type = "dylib"];
extern mod rlib;
pub fn dylib() { rlib::rlib() }

View File

@ -0,0 +1,7 @@
extern mod dylib;
extern mod rlib;
fn main() {
dylib::dylib();
rlib::rlib();
}

View File

@ -0,0 +1,2 @@
#[crate_type = "rlib"];
pub fn rlib() {}

View File

@ -0,0 +1,8 @@
-include ../tools.mk
all:
$(RUSTC) bar.rs --dylib --rlib
$(RUSTC) foo.rs -Z prefer-dynamic
$(call RUN,foo)
rm $(TMPDIR)/*bar*
$(call FAILS,foo)

View File

@ -0,0 +1 @@
pub fn bar() {}

View File

@ -0,0 +1,5 @@
extern mod bar;
fn main() {
bar::bar();
}

View File

@ -0,0 +1,8 @@
-include ../tools.mk
all:
$(RUSTC) bar.rs --dylib --rlib
ls $(TMPDIR)/$(call RLIB_GLOB,bar)
$(RUSTC) foo.rs
rm $(TMPDIR)/*bar*
$(call RUN,foo)

View File

@ -0,0 +1 @@
pub fn bar() {}

View File

@ -0,0 +1,5 @@
extern mod bar;
fn main() {
bar::bar();
}

View File

@ -0,0 +1,10 @@
-include ../tools.mk
all:
$(RUSTC) m1.rs
$(RUSTC) m2.rs
$(RUSTC) m3.rs
$(RUSTC) m4.rs
$(call RUN,m4)
rm $(TMPDIR)/*lib
$(call RUN,m4)

View File

@ -0,0 +1,2 @@
#[crate_type = "rlib"];
pub fn m1() {}

View File

@ -0,0 +1,4 @@
#[crate_type = "rlib"];
extern mod m1;
pub fn m2() { m1::m1() }

View File

@ -0,0 +1,4 @@
#[crate_type = "rlib"];
extern mod m2;
pub fn m3() { m2::m2() }

View File

@ -0,0 +1,3 @@
extern mod m3;
fn main() { m3::m3() }

View File

@ -0,0 +1,5 @@
-include ../tools.mk
all:
$(RUSTC) bar.rs --dylib
$(RUSTC) foo.rs
$(call RUN,foo)

View File

@ -0,0 +1 @@
pub fn bar() {}

View File

@ -0,0 +1,5 @@
extern mod bar;
fn main() {
bar::bar();
}

View File

@ -0,0 +1,5 @@
-include ../tools.mk
all:
$(RUSTC) bar.rs --rlib
$(RUSTC) foo.rs
$(call RUN,foo)

View File

@ -0,0 +1 @@
pub fn bar() {}

View File

@ -0,0 +1,5 @@
extern mod bar;
fn main() {
bar::bar();
}

View File

@ -0,0 +1,6 @@
-include ../tools.mk
all:
$(RUSTC) lib.rs
$(RUSTC) main.rs
$(call RUN,main)

View File

@ -0,0 +1,15 @@
#[crate_type = "rlib"];
pub static mut statik: int = 0;
struct A;
impl Drop for A {
fn drop(&mut self) {
unsafe { statik = 1; }
}
}
pub fn callback(f: ||) {
let _a = A;
f();
}

View File

@ -0,0 +1,25 @@
extern mod lib;
use std::task;
static mut statik: int = 0;
struct A;
impl Drop for A {
fn drop(&mut self) {
unsafe { statik = 1; }
}
}
fn main() {
do task::try {
let _a = A;
lib::callback(|| fail!());
1
};
unsafe {
assert!(lib::statik == 1);
assert!(statik == 1);
}
}

View File

@ -0,0 +1,27 @@
RUSTC := $(RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR)
CC := $(CC) -L $(TMPDIR)
RUN = $(TMPDIR)/$(1)
FAILS = $(TMPDIR)/$(1) && exit 1 || exit 0
RLIB_GLOB = lib$(1)*.rlib
STATICLIB = $(TMPDIR)/lib$(1).a
STATICLIB_GLOB = lib$(1)*.a
ifeq ($(shell uname),Darwin)
DYLIB_GLOB = lib$(1)*.dylib
DYLIB = $(TMPDIR)/lib$(1).dylib
else
DYLIB_GLOB = lib$(1)*.so
DYLIB = $(TMPDIR)/lib$(1).so
endif
%.a: %.o
ar crus $@ $<
%.dylib: %.o
ld -o $@ $< -dylib
%.so: %.o
ld -o $@ $< -shared
$(TMPDIR)/lib%.o: %.c
$(CC) -c -o $@ $<