aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeffrey Yasskin <[email protected]>2010-07-24 12:33:29 -0700
committerGraydon Hoare <[email protected]>2010-08-06 17:17:04 -0700
commit987589e94691a82a551677740d47444f6c9acfd5 (patch)
treeb92d1528f6a05ed9250b489f300241a43bdb1777 /src
parentFix LLVM translation of modules. (diff)
downloadrust-987589e94691a82a551677740d47444f6c9acfd5.tar.xz
rust-987589e94691a82a551677740d47444f6c9acfd5.zip
Change the destructor-ordering test to use channels instead of a shared mutable object.
This test used to take advantage of a hole in the type system that allows objects with destructors to refer to stateful objects.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile1
-rw-r--r--src/test/run-pass/destructor-ordering.rs117
2 files changed, 79 insertions, 39 deletions
diff --git a/src/Makefile b/src/Makefile
index 280ccc6c..aaf2e94f 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -389,6 +389,7 @@ TEST_XFAILS_X86 := $(TASK_XFAILS) \
test/run-pass/child-outlives-parent.rs \
test/run-pass/clone-with-exterior.rs \
test/run-pass/constrained-type.rs \
+ test/run-pass/destructor-ordering.rs \
test/run-pass/obj-as.rs \
test/run-pass/vec-slice.rs \
test/run-pass/fn-lval.rs \
diff --git a/src/test/run-pass/destructor-ordering.rs b/src/test/run-pass/destructor-ordering.rs
index 99479c55..f7f5b8c8 100644
--- a/src/test/run-pass/destructor-ordering.rs
+++ b/src/test/run-pass/destructor-ordering.rs
@@ -1,58 +1,93 @@
-// We share an instance of this type among all the destructor-order
-// checkers. It tracks how many destructors have run so far and
-// 'fail's when one runs out of order.
-// FIXME: Make it easier to collect a failure message.
-state obj order_tracker(mutable int init) {
- fn assert_order(int expected, str fail_message) {
- if (expected != init) {
- log expected;
+// This test checks that destructors run in the right order. Because
+// stateful objects can't have destructors, we have the destructors
+// record their expected order into a channel when they execute (so
+// the object becomes 'io' rather than 'state'). Then each test case
+// asserts that the channel produces values in ascending order.
+//
+// FIXME: Write an int->str function and concatenate the whole failure
+// message into a single log statement (or, even better, a print).
+//
+// FIXME: check_order should take only 1 line in a test, not 2+a block
+// block. Since destructor-having objects can't refer to mutable state
+// (like the port), we'd need a with-like construct to do the same for
+// stateful objects within a scope.
+//
+// FIXME #21: Each test should execute in its own task, so it can fail
+// independently, writing its error message to a channel that the
+// parent task aggregates.
+
+type order_info = rec(int order, str msg);
+
+io fn check_order(port[order_info] expected_p) {
+ chan(expected_p) <| rec(order=-1, msg="");
+ let mutable int actual = 0;
+ auto expected <- expected_p; // FIXME #121: Workaround for while(true) bug.
+ auto done = -1; // FIXME: Workaround for typechecking bug.
+ while(expected.order != done) {
+ if (expected.order != actual) {
+ log expected.order;
log " != ";
- log init;
- log fail_message;
+ log actual;
+ log expected.msg;
fail;
}
- init += 1;
+ actual += 1;
+ expected <- expected_p;
}
}
-obj dorder(@order_tracker tracker, int order, str message) {
+obj dorder(chan[order_info] expected, int order, str message) {
drop {
- tracker.assert_order(order, message);
+ expected <| rec(order=order, msg=message);
}
}
-fn test_simple() {
- auto tracker = @order_tracker(0);
+io fn test_simple() {
+ let port[order_info] tracker_p = port();
+ auto tracker = chan(tracker_p);
dorder(tracker, 1, "Reverse decl order");
dorder(tracker, 0, "Reverse decl order");
+ check_order(tracker_p);
}
-fn test_block() {
- auto tracker = @order_tracker(0);
- dorder(tracker, 2, "Before block");
+io fn test_block() {
+ let port[order_info] tracker_p = port();
+ auto tracker = chan(tracker_p);
{
- dorder(tracker, 0, "Inside block");
+ dorder(tracker, 2, "Before block");
+ {
+ dorder(tracker, 0, "Inside block");
+ }
+ dorder(tracker, 1, "After block");
}
- dorder(tracker, 1, "After block");
+ check_order(tracker_p);
}
-fn test_decl_v_init() {
- auto tracker = @order_tracker(0);
- auto var1;
- auto var2;
- var2 = dorder(tracker, 0, "decl, not init");
- var1 = dorder(tracker, 1, "decl, not init");
+io fn test_decl_v_init() {
+ let port[order_info] tracker_p = port();
+ auto tracker = chan(tracker_p);
+ {
+ auto var1;
+ auto var2;
+ var2 = dorder(tracker, 0, "decl, not init");
+ var1 = dorder(tracker, 1, "decl, not init");
+ }
+ check_order(tracker_p);
}
-fn test_overwritten_obj() {
- auto tracker = @order_tracker(0);
- auto var1 = dorder(tracker, 0, "overwritten object destroyed first");
- auto var2 = dorder(tracker, 2, "destroyed at end of scope");
- var1 = dorder(tracker, 3, "overwriter deleted in rev decl order");
+io fn test_overwritten_obj() {
+ let port[order_info] tracker_p = port();
+ auto tracker = chan(tracker_p);
{
- dorder(tracker, 1, "overwritten object destroyed before end of scope");
+ auto var1 = dorder(tracker, 0, "overwritten object destroyed first");
+ auto var2 = dorder(tracker, 2, "destroyed at end of scope");
+ var1 = dorder(tracker, 3, "overwriter deleted in rev decl order");
+ {
+ dorder(tracker, 1, "overwritten object destroyed before end of scope");
+ }
}
+ check_order(tracker_p);
}
// Used to embed dorder objects into an expression. Note that the
@@ -60,17 +95,21 @@ fn test_overwritten_obj() {
fn combine_dorders(dorder d1, dorder d2) -> int {
ret 1;
}
-fn test_expression_destroyed_right_to_left() {
- auto tracker = @order_tracker(0);
- combine_dorders(dorder(tracker, 4, ""), dorder(tracker, 3, ""))
- / combine_dorders(dorder(tracker, 2, ""), dorder(tracker, 1, ""));
+io fn test_expression_destroyed_right_to_left() {
+ let port[order_info] tracker_p = port();
+ auto tracker = chan(tracker_p);
{
- dorder(tracker, 0,
- "expression objects live to end of block, not statement");
+ combine_dorders(dorder(tracker, 4, ""), dorder(tracker, 3, ""))
+ / combine_dorders(dorder(tracker, 2, ""), dorder(tracker, 1, ""));
+ {
+ dorder(tracker, 0,
+ "expression objects live to end of block, not statement");
+ }
}
+ check_order(tracker_p);
}
-fn main() {
+io fn main() {
test_simple();
test_block();
test_decl_v_init();