aboutsummaryrefslogtreecommitdiffstats
path: root/util/system/context_ut.cpp
blob: 8c0eb2cbaa0ef35f0e077a2ceed4be1413622952 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include "context.h" 
 
#include <library/cpp/testing/unittest/registar.h>
 
#include <util/generic/deque.h> 
#include <util/generic/yexception.h>
 
Y_UNIT_TEST_SUITE(TestContext) {
    template <class F> 
    static TContClosure Wrap(F& f) { 
        struct TW: public ITrampoLine { 
            inline TW(F* ff) noexcept 
                : F_(ff) 
            { 
            } 
 
            void DoRun() override { 
                (*F_)(); 
            } 
 
            F* F_; 
            char Buf[1000000]; 
        }; 
 
        static TDeque<TW> w;
 
        auto& tw = w.emplace_back(&f); 
 
        return {&tw, TArrayRef(tw.Buf, sizeof(tw.Buf))};
    } 
 
    Y_UNIT_TEST(TestExceptionSafety) {
        TExceptionSafeContext main; 
        TExceptionSafeContext* volatile nextPtr = nullptr; 
 
        bool hasUncaught = true;
 
        auto func = [&]() {
            hasUncaught = UncaughtException();
            nextPtr->SwitchTo(&main); 
        }; 
 
        auto closure = Wrap(func); 
 
        TExceptionSafeContext next(closure); 
 
        nextPtr = &next; 
 
        struct THelper { 
            inline ~THelper() { 
                M->SwitchTo(N); 
            } 
 
            TExceptionSafeContext* M; 
            TExceptionSafeContext* N; 
        }; 
 
        bool throwed = false; 
 
        try { 
            THelper helper{&main, &next}; 
 
            throw 1; 
        } catch (...) { 
            throwed = true; 
        } 
 
        UNIT_ASSERT(throwed); 
        UNIT_ASSERT(!hasUncaught);
    } 
}