Belle II Software development
ScopeGuards.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <framework/utilities/ScopeGuard.h>
10#include <framework/utilities/Utils.h>
11#include <gtest/gtest.h>
12#include <filesystem>
13
14namespace {
16 struct IntSetterGetterFunctor {
18 explicit IntSetterGetterFunctor(int& reference): ref(reference) {}
20 void operator()(const int& v) { ref = v; }
22 int operator()() const { return ref; }
24 int& ref;
25 };
26
28 TEST(ScopeGuards, IntRef)
29 {
30 int old{5};
31 {
32 auto guard = Belle2::ScopeGuard::guardValue(old); // cppcheck-suppress unreadVariable
33 ASSERT_EQ(old, 5);
34 old = 17;
35 }
36 ASSERT_EQ(old, 5);
37 {
38 auto guard = Belle2::ScopeGuard::guardValue(old, 17); // cppcheck-suppress unreadVariable
39 ASSERT_EQ(old, 17);
40 }
41 ASSERT_EQ(old, 5);
42 {
43 auto guard = Belle2::ScopeGuard::guardValue(old, 17);
44 ASSERT_EQ(old, 17);
45 guard.release();
46 }
47 ASSERT_EQ(old, 17);
48 }
49
51 TEST(ScopeGuards, IntSetterGetter)
52 {
53 int old{5};
54 auto setter = [&old](int v) {old = v;};
55 auto getter = [&old]() {return old;};
56 {
57 auto guard = Belle2::ScopeGuard::guardGetterSetter(getter, setter);
58 ASSERT_EQ(old, 5);
59 old = 17;
60 }
61 ASSERT_EQ(old, 5);
62 {
63 auto guard = Belle2::ScopeGuard::guardGetterSetter(getter, setter, 17);
64 ASSERT_EQ(old, 17);
65 }
66 ASSERT_EQ(old, 5);
67 {
68 auto guard = Belle2::ScopeGuard::guardGetterSetter(getter, setter, 17);
69 ASSERT_EQ(old, 17);
70 guard.release();
71 }
72 ASSERT_EQ(old, 17);
73 }
74
76 TEST(ScopeGuards, IntSetterGetterFunctor)
77 {
78 int old{5};
79 IntSetterGetterFunctor functor(old);
80 {
81 auto guard = Belle2::ScopeGuard::guardFunctor(functor); // cppcheck-suppress unreadVariable
82 ASSERT_EQ(old, 5);
83 old = 17;
84 }
85 ASSERT_EQ(old, 5);
86 {
87 auto guard = Belle2::ScopeGuard::guardFunctor(functor, 17); // cppcheck-suppress unreadVariable
88 ASSERT_EQ(old, 17);
89 }
90 ASSERT_EQ(old, 5);
91 {
92 auto guard = Belle2::ScopeGuard::guardFunctor(functor, 17);
93 ASSERT_EQ(old, 17);
94 guard.release();
95 }
96 ASSERT_EQ(old, 17);
97 {
98 // cppcheck-suppress unreadVariable
100 [&old](int v) { old = v; },
101 [&old]() { return old; }
102 }, 21);
103 ASSERT_EQ(old, 21);
104 }
105 ASSERT_EQ(old, 17);
106 }
107
111 TEST(ScopeGuards, StringReference)
112 {
113 std::string value{"before"};
114 {
115 auto guard = Belle2::ScopeGuard::guardValue(value, "after"); // cppcheck-suppress unreadVariable
116 ASSERT_EQ(value, "after");
117 }
118 ASSERT_EQ(value, "before");
119 {
120 // cppcheck-suppress unreadVariable
122 [&value](const std::string & v) { value = v; },
123 [&value]() { return value; }
124 }, "after");
125 ASSERT_EQ(value, "after");
126 };
127 ASSERT_EQ(value, "before");
128 }
129
131 TEST(ScopeGuards, StreamState)
132 {
133 std::stringstream buf;
134 buf << "a:" << std::setprecision(4) << 1.2;
135 {
136 auto guard1 = Belle2::ScopeGuard::guardStreamState(buf); // cppcheck-suppress unreadVariable
137 buf << ":b:" << std::fixed << std::setprecision(4) << 2.3;
138 {
139 // cppcheck-suppress unreadVariable
140 auto guard3 = Belle2::ScopeGuard::guardStreamState(buf);
141 buf << ":c:" << std::setprecision(5) << std::setw(10) << std::setfill('-') << 3.4;
142 }
143
144 buf << ":d:" << std::scientific << 4.5;
145 }
146 buf << ":e:" << 5.4;
147 ASSERT_EQ(buf.str(), "a:1.2:b:2.3000:c:---3.40000:d:4.5000e+00:e:5.4");
148 }
149
151 TEST(ScopeGuards, WorkingDirectory)
152 {
153 std::string start{std::filesystem::current_path().c_str()};
154 std::string tmpdir(std::filesystem::temp_directory_path().c_str());
155 std::string root("/");
156 {
157 auto guard1 = Belle2::ScopeGuard::guardWorkingDirectory( // cppcheck-suppress unreadVariable
158 std::filesystem::temp_directory_path().c_str());
159 ASSERT_EQ(tmpdir, std::filesystem::current_path().c_str());
160 {
162 ASSERT_EQ(root, std::filesystem::current_path().c_str());
163 guard2.release();
164 }
165 ASSERT_EQ(root, std::filesystem::current_path().c_str());
166 }
167 ASSERT_EQ(start, std::filesystem::current_path().c_str());
168 }
169
170
172 TEST(ScopeGuards, Batch)
173 {
174 const bool start = gROOT->IsBatch();
175 {
176 auto guard1 = Belle2::ScopeGuard::guardBatchMode(); // cppcheck-suppress unreadVariable
177 ASSERT_EQ(true, gROOT->IsBatch());
178 {
179 auto guard2 = Belle2::ScopeGuard::guardBatchMode(false); // cppcheck-suppress unreadVariable
180 ASSERT_EQ(false, gROOT->IsBatch());
181 }
182 ASSERT_EQ(true, gROOT->IsBatch());
183 }
184 ASSERT_EQ(start, gROOT->IsBatch());
185 }
186}
static ScopeGuard guardStreamState(std::basic_ios< CharT, Traits > &stream)
Create a ScopeGuard for the state of a stream to reset all the formatting at the end of the object li...
Definition: ScopeGuard.h:262
static ScopeGuard guardValue(T &reference)
Create a ScopeGuard for a value: The content of reference will be copied and reset when the returned ...
Definition: ScopeGuard.h:76
static ScopeGuard guardGetterSetter(Getter getter, Setter setter)
Create a ScopeGuard from a getter and setter: On construction the getter object is called to obtain a...
Definition: ScopeGuard.h:137
static ScopeGuard guardFunctor(Functor functor)
Create a ScopeGuard from a functor object with appropriately overloaded operator() calls to get and s...
Definition: ScopeGuard.h:188
static ScopeGuard guardBatchMode(bool batchMode=true)
Create a ScopeGuard to turn ROOT into batch mode and restore the initial batch mode status after the ...
Definition: ScopeGuard.h:352
static ScopeGuard guardWorkingDirectory()
Create a ScopeGuard of the current working directory.
Definition: ScopeGuard.h:296
Helper struct for the C++17 std::visit overload pattern to allow simple use of variants.
Definition: Utils.h:26