1module lib;
2
3// test EH
4void throwException()
5{
6    throw new Exception(null);
7}
8
9Exception collectException(void delegate() dg)
10{
11    try
12        dg();
13    catch (Exception e)
14        return e;
15    return null;
16}
17
18// test GC
19__gshared Object root;
20void alloc() { root = new Object(); }
21void access() { assert(root.toString() !is null); } // vtbl call will fail if finalized
22void free() { root = null; }
23
24Object tls_root;
25void tls_alloc() { tls_root = new Object(); }
26void tls_access() { assert(tls_root.toString() !is null); } // vtbl call will fail if finalized
27void tls_free() { tls_root = null; }
28
29void stack(alias func)()
30{
31    // allocate some extra stack space to not keep references to GC memory on the scanned stack
32    ubyte[1024] buf = void;
33    func();
34}
35
36void testGC()
37{
38    import core.memory;
39
40    stack!alloc();
41    stack!tls_alloc();
42    stack!access();
43    stack!tls_access();
44    GC.collect();
45    stack!tls_access();
46    stack!access();
47    stack!tls_free();
48    stack!free();
49}
50
51// test Init
52import core.atomic : atomicOp;
53shared uint shared_static_ctor, shared_static_dtor, static_ctor, static_dtor;
54shared static this() { if (atomicOp!"+="(shared_static_ctor, 1) != 1) assert(0); }
55shared static ~this() { if (atomicOp!"+="(shared_static_dtor, 1) != 1) assert(0); }
56static this() { atomicOp!"+="(static_ctor, 1); }
57static ~this() { atomicOp!"+="(static_dtor, 1); }
58
59extern(C) int runTests()
60{
61    try
62        runTestsImpl();
63    catch (Throwable)
64        return 0;
65    return 1;
66}
67
68void runTestsImpl()
69{
70    import core.thread;
71
72    bool passed;
73    try
74        throwException();
75    catch (Exception e)
76        passed = true;
77    assert(passed);
78    assert(collectException({throwException();}) !is null);
79
80    testGC();
81
82    assert(shared_static_ctor == 1);
83    assert(static_ctor == 1);
84    static void run()
85    {
86        assert(static_ctor == 2);
87        assert(shared_static_ctor == 1);
88        testGC();
89    }
90    auto thr = new Thread(&run);
91    thr.start();
92    thr.join();
93    assert(static_dtor == 1);
94
95    passed = false;
96    foreach (m; ModuleInfo)
97        if (m.name == "lib") passed = true;
98    assert(passed);
99}
100
101// Provide a way to initialize D from C programs that are D agnostic.
102import core.runtime : rt_init, rt_term;
103
104extern(C) int lib_init()
105{
106    return rt_init();
107}
108
109extern(C) int lib_term()
110{
111    return rt_term();
112}
113
114shared size_t* _finalizeCounter;
115
116class MyFinalizer
117{
118    ~this()
119    {
120        import core.atomic;
121        atomicOp!"+="(*_finalizeCounter, 1);
122    }
123}
124
125class MyFinalizerBig : MyFinalizer
126{
127    ubyte[4096] _big = void;
128}
129
130extern(C) void setFinalizeCounter(shared(size_t)* p)
131{
132    _finalizeCounter = p;
133}
134