proxygen
SettingsTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2018-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
17 #include <folly/Format.h>
19 
22 
23 namespace some_ns {
25  follytest,
26  some_flag,
28  "default",
29  "Description");
31  follytest,
32  unused,
34  "unused_default",
35  "Not used, but should still be in the list");
37  follytest,
38  multi_token_type,
39  unsigned int,
40  123,
41  "Test that multi-token type names can be used");
42 // Enable to test runtime collision checking logic
43 #if 0
44 FOLLY_SETTING_DEFINE(follytest, internal_flag_to_a, std::string,
45  "collision_with_a",
46  "Collision_with_a");
47 #endif
48 
49 /* Test user defined type support */
52  if (value == "a") {
53  value_ = 0;
54  } else if (value == "b") {
55  value_ = 100;
56  } else {
57  throw std::runtime_error("Invalid value passed to UserDefinedType ctor");
58  }
59  }
60 
61  bool operator==(const UserDefinedType& other) const {
62  return value_ == other.value_;
63  }
64 
65  int value_;
66 };
67 /* Note: conversion intentionally to different strings to test that this
68  function is called */
69 template <class String>
70 void toAppend(const UserDefinedType& t, String* out) {
71  if (t.value_ == 0) {
72  out->append("a_out");
73  } else if (t.value_ == 100) {
74  out->append("b_out");
75  } else {
76  throw std::runtime_error("Can't convert UserDefinedType to string");
77  }
78 }
79 
81  follytest,
82  user_defined,
84  "b",
85  "User defined type constructed from string");
86 
87 } // namespace some_ns
88 
89 TEST(Settings, user_defined) {
90  EXPECT_EQ(some_ns::FOLLY_SETTING(follytest, user_defined)->value_, 100);
91  {
93  EXPECT_TRUE(sn.setFromString("follytest_user_defined", "a", "test"));
94  sn.publish();
95  EXPECT_EQ(some_ns::FOLLY_SETTING(follytest, user_defined)->value_, 0);
96  }
97  {
99  auto info = sn.getAsString("follytest_user_defined");
100  EXPECT_TRUE(info.hasValue());
101  EXPECT_EQ(info->first, "a_out");
102  EXPECT_EQ(info->second, "test");
103  }
104  {
106  EXPECT_THROW(
107  sn.setFromString("follytest_user_defined", "c", "test2"),
108  std::runtime_error);
109  sn.publish();
110  EXPECT_EQ(some_ns::FOLLY_SETTING(follytest, user_defined)->value_, 0);
111  }
112  {
114  auto info = sn.getAsString("follytest_user_defined");
115  EXPECT_TRUE(info.hasValue());
116  EXPECT_EQ(info->first, "a_out");
117  EXPECT_EQ(info->second, "test");
118  }
119  {
121  EXPECT_TRUE(sn.resetToDefault("follytest_user_defined"));
122  sn.publish();
123  EXPECT_EQ(some_ns::FOLLY_SETTING(follytest, user_defined)->value_, 100);
124  }
125  {
127  auto info = sn.getAsString("follytest_user_defined");
128  EXPECT_TRUE(info.hasValue());
129  EXPECT_EQ(info->first, "b_out");
130  EXPECT_EQ(info->second, "default");
131  }
132  /* Test that intentionally setting to something non-converteable fails */
133  some_ns::UserDefinedType bad("a");
134  bad.value_ = 50;
135  EXPECT_THROW(
136  some_ns::FOLLY_SETTING(follytest, user_defined).set(bad),
137  std::runtime_error);
138  EXPECT_EQ(some_ns::FOLLY_SETTING(follytest, user_defined)->value_, 100);
139  {
141  auto info = sn.getAsString("follytest_user_defined");
142  EXPECT_TRUE(info.hasValue());
143  EXPECT_EQ(info->first, "b_out");
144  EXPECT_EQ(info->second, "default");
145  }
146 }
147 
148 TEST(Settings, basic) {
149  EXPECT_EQ(a_ns::a_func(), 1245);
150  EXPECT_EQ(b_ns::b_func(), "testbasdf");
151  EXPECT_EQ(*some_ns::FOLLY_SETTING(follytest, some_flag), "default");
152  // Test -> API
153  EXPECT_EQ(some_ns::FOLLY_SETTING(follytest, some_flag)->size(), 7);
154  a_ns::FOLLY_SETTING(follytest, public_flag_to_a).set(100);
155  EXPECT_EQ(*a_ns::FOLLY_SETTING(follytest, public_flag_to_a), 100);
156  EXPECT_EQ(a_ns::getRemote(), 100);
157  a_ns::setRemote(200);
158  EXPECT_EQ(*a_ns::FOLLY_SETTING(follytest, public_flag_to_a), 200);
159  EXPECT_EQ(a_ns::getRemote(), 200);
160  {
162  auto res = sn.getAsString("follytest_public_flag_to_a");
163  EXPECT_TRUE(res.hasValue());
164  EXPECT_EQ(res->first, "200");
165  EXPECT_EQ(res->second, "remote_set");
166  }
167  {
168  auto meta = folly::settings::getSettingsMeta("follytest_public_flag_to_a");
169  EXPECT_TRUE(meta.hasValue());
170  const auto& md = meta.value();
171  EXPECT_EQ(md.project, "follytest");
172  EXPECT_EQ(md.name, "public_flag_to_a");
173  EXPECT_EQ(md.typeStr, "int");
174  EXPECT_EQ(md.typeId, typeid(int));
175  }
176  {
177  auto meta = folly::settings::getSettingsMeta("follytest_some_flag");
178  EXPECT_TRUE(meta.hasValue());
179  const auto& md = meta.value();
180  EXPECT_EQ(md.project, "follytest");
181  EXPECT_EQ(md.name, "some_flag");
182  EXPECT_EQ(md.typeStr, "std::string");
183  EXPECT_EQ(md.typeId, typeid(std::string));
184  }
185  {
187  auto res = sn.getAsString("follytest_nonexisting");
188  EXPECT_FALSE(res.hasValue());
189  }
190  {
192  EXPECT_TRUE(
193  sn.setFromString("follytest_public_flag_to_a", "300", "from_string"));
194  sn.publish();
195  EXPECT_EQ(*a_ns::FOLLY_SETTING(follytest, public_flag_to_a), 300);
196  }
197  EXPECT_EQ(a_ns::getRemote(), 300);
198  {
200  auto res = sn.getAsString("follytest_public_flag_to_a");
201  EXPECT_TRUE(res.hasValue());
202  EXPECT_EQ(res->first, "300");
203  EXPECT_EQ(res->second, "from_string");
204  }
205  {
207  EXPECT_FALSE(
208  sn.setFromString("follytest_nonexisting", "300", "from_string"));
209  }
210  EXPECT_EQ(
211  some_ns::FOLLY_SETTING(follytest, multi_token_type).defaultValue(), 123);
212  EXPECT_EQ(
213  a_ns::FOLLY_SETTING(follytest, public_flag_to_a).defaultValue(), 456);
214  EXPECT_EQ(
215  b_ns::FOLLY_SETTING(follytest, public_flag_to_b).defaultValue(), "basdf");
216  EXPECT_EQ(
217  some_ns::FOLLY_SETTING(follytest, some_flag).defaultValue(), "default");
218  EXPECT_EQ(
219  some_ns::FOLLY_SETTING(follytest, user_defined).defaultValue(),
221  {
222  std::string allFlags;
224  sn.forEachSetting([&allFlags](
227  folly::StringPiece reason) {
228  if (meta.typeId == typeid(int)) {
229  EXPECT_EQ(meta.typeStr, "int");
230  } else if (meta.typeId == typeid(std::string)) {
231  EXPECT_EQ(meta.typeStr, "std::string");
232  } else if (meta.typeId == typeid(unsigned int)) {
233  EXPECT_EQ(meta.typeStr, "unsigned int");
234  } else if (meta.typeId == typeid(some_ns::UserDefinedType)) {
235  EXPECT_EQ(meta.typeStr, "UserDefinedType");
236  } else {
237  ASSERT_FALSE(true);
238  }
239  allFlags += folly::sformat(
240  "{}/{}/{}/{}/{}/{}/{}\n",
241  meta.project,
242  meta.name,
243  meta.typeStr,
244  meta.defaultStr,
245  meta.description,
246  value,
247  reason);
248  });
249  EXPECT_EQ(
250  allFlags,
251  "follytest/internal_flag_to_a/int/789/Desc of int/789/default\n"
252  "follytest/internal_flag_to_b/std::string/\"test\"/Desc of str/test/default\n"
253  "follytest/multi_token_type/unsigned int/123/Test that multi-token type names can be used/123/default\n"
254  "follytest/public_flag_to_a/int/456/Public flag to a/300/from_string\n"
255  "follytest/public_flag_to_b/std::string/\"basdf\"/Public flag to b/basdf/default\n"
256  "follytest/some_flag/std::string/\"default\"/Description/default/default\n"
257  "follytest/unused/std::string/\"unused_default\"/Not used, but should still be in the list/unused_default/default\n"
258  "follytest/user_defined/UserDefinedType/\"b\"/User defined type constructed from string/b_out/default\n");
259  }
260  {
262  EXPECT_TRUE(sn.resetToDefault("follytest_public_flag_to_a"));
263  sn.publish();
264  EXPECT_EQ(*a_ns::FOLLY_SETTING(follytest, public_flag_to_a), 456);
265  EXPECT_EQ(a_ns::getRemote(), 456);
266  }
267  {
269  EXPECT_FALSE(sn.resetToDefault("follytest_nonexisting"));
270  }
271 }
272 
273 TEST(Settings, snapshot) {
274  // Test discarding a snapshot
275  {
276  folly::settings::Snapshot snapshot;
277 
278  EXPECT_EQ(*some_ns::FOLLY_SETTING(follytest, some_flag), "default");
279  EXPECT_EQ(
280  *snapshot(some_ns::FOLLY_SETTING(follytest, some_flag)), "default");
281 
282  // Set the global value, snapshot doesn't see it
283  some_ns::FOLLY_SETTING(follytest, some_flag).set("global_value");
284  EXPECT_EQ(*some_ns::FOLLY_SETTING(follytest, some_flag), "global_value");
285  EXPECT_EQ(
286  *snapshot(some_ns::FOLLY_SETTING(follytest, some_flag)), "default");
287 
288  // Set the value in the snapshot only
289  snapshot(some_ns::FOLLY_SETTING(follytest, some_flag))
290  .set("snapshot_value");
291  EXPECT_EQ(*some_ns::FOLLY_SETTING(follytest, some_flag), "global_value");
292  EXPECT_EQ(
293  *snapshot(some_ns::FOLLY_SETTING(follytest, some_flag)),
294  "snapshot_value");
295  }
296  // Discard the snapshot
297  EXPECT_EQ(*some_ns::FOLLY_SETTING(follytest, some_flag), "global_value");
298 
299  // Test publishing a snapshot
300  {
301  folly::settings::Snapshot snapshot;
302 
303  // Set the value in the snapshot only
304  EXPECT_EQ(*some_ns::FOLLY_SETTING(follytest, some_flag), "global_value");
305  EXPECT_EQ(
306  *snapshot(some_ns::FOLLY_SETTING(follytest, some_flag)),
307  "global_value");
308  snapshot(some_ns::FOLLY_SETTING(follytest, some_flag))
309  .set("snapshot_value2");
310  EXPECT_EQ(*some_ns::FOLLY_SETTING(follytest, some_flag), "global_value");
311  EXPECT_EQ(
312  *snapshot(some_ns::FOLLY_SETTING(follytest, some_flag)),
313  "snapshot_value2");
314 
315  // Set the global value, snapshot doesn't see it
316  some_ns::FOLLY_SETTING(follytest, some_flag).set("global_value2");
317  EXPECT_EQ(*some_ns::FOLLY_SETTING(follytest, some_flag), "global_value2");
318  EXPECT_EQ(
319  *snapshot(some_ns::FOLLY_SETTING(follytest, some_flag)),
320  "snapshot_value2");
321  snapshot.publish();
322  }
323 
324  EXPECT_EQ(*some_ns::FOLLY_SETTING(follytest, some_flag), "snapshot_value2");
325 
326  // Snapshots at different points in time
327  {
328  some_ns::FOLLY_SETTING(follytest, some_flag).set("a");
329  a_ns::FOLLY_SETTING(follytest, public_flag_to_a).set(123);
330 
331  folly::settings::Snapshot snapshot_1;
332 
333  EXPECT_EQ(*some_ns::FOLLY_SETTING(follytest, some_flag), "a");
334  EXPECT_EQ(*snapshot_1(some_ns::FOLLY_SETTING(follytest, some_flag)), "a");
335  EXPECT_EQ(*a_ns::FOLLY_SETTING(follytest, public_flag_to_a), 123);
336  EXPECT_EQ(
337  *snapshot_1(a_ns::FOLLY_SETTING(follytest, public_flag_to_a)), 123);
338 
339  some_ns::FOLLY_SETTING(follytest, some_flag).set("b");
340  EXPECT_EQ(*some_ns::FOLLY_SETTING(follytest, some_flag), "b");
341  EXPECT_EQ(*snapshot_1(some_ns::FOLLY_SETTING(follytest, some_flag)), "a");
342  EXPECT_EQ(*a_ns::FOLLY_SETTING(follytest, public_flag_to_a), 123);
343  EXPECT_EQ(
344  *snapshot_1(a_ns::FOLLY_SETTING(follytest, public_flag_to_a)), 123);
345 
346  folly::settings::Snapshot snapshot_2;
347  EXPECT_EQ(*some_ns::FOLLY_SETTING(follytest, some_flag), "b");
348  EXPECT_EQ(*snapshot_1(some_ns::FOLLY_SETTING(follytest, some_flag)), "a");
349  EXPECT_EQ(*snapshot_2(some_ns::FOLLY_SETTING(follytest, some_flag)), "b");
350  EXPECT_EQ(*a_ns::FOLLY_SETTING(follytest, public_flag_to_a), 123);
351  EXPECT_EQ(
352  *snapshot_1(a_ns::FOLLY_SETTING(follytest, public_flag_to_a)), 123);
353  EXPECT_EQ(
354  *snapshot_2(a_ns::FOLLY_SETTING(follytest, public_flag_to_a)), 123);
355 
356  some_ns::FOLLY_SETTING(follytest, some_flag).set("c");
357  EXPECT_EQ(*some_ns::FOLLY_SETTING(follytest, some_flag), "c");
358  EXPECT_EQ(*snapshot_1(some_ns::FOLLY_SETTING(follytest, some_flag)), "a");
359  EXPECT_EQ(*snapshot_2(some_ns::FOLLY_SETTING(follytest, some_flag)), "b");
360  EXPECT_EQ(*a_ns::FOLLY_SETTING(follytest, public_flag_to_a), 123);
361  EXPECT_EQ(
362  *snapshot_1(a_ns::FOLLY_SETTING(follytest, public_flag_to_a)), 123);
363  EXPECT_EQ(
364  *snapshot_2(a_ns::FOLLY_SETTING(follytest, public_flag_to_a)), 123);
365 
366  a_ns::FOLLY_SETTING(follytest, public_flag_to_a).set(456);
367  EXPECT_EQ(*some_ns::FOLLY_SETTING(follytest, some_flag), "c");
368  EXPECT_EQ(*snapshot_1(some_ns::FOLLY_SETTING(follytest, some_flag)), "a");
369  EXPECT_EQ(*snapshot_2(some_ns::FOLLY_SETTING(follytest, some_flag)), "b");
370  EXPECT_EQ(*a_ns::FOLLY_SETTING(follytest, public_flag_to_a), 456);
371  EXPECT_EQ(
372  *snapshot_1(a_ns::FOLLY_SETTING(follytest, public_flag_to_a)), 123);
373  EXPECT_EQ(
374  *snapshot_2(a_ns::FOLLY_SETTING(follytest, public_flag_to_a)), 123);
375  }
376 }
UserDefinedType(folly::StringPiece value)
bool setFromString(StringPiece settingName, StringPiece newValue, StringPiece reason) override
Definition: Settings.cpp:62
def info()
Definition: deadlock.py:447
void toAppend(const UserDefinedType &t, String *out)
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
std::string sformat(StringPiece fmt, Args &&...args)
Definition: Format.h:280
const std::type_info & typeId
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
static void basic()
void publish() override
Definition: Settings.cpp:176
int getRemote()
Definition: a.cpp:35
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
FOLLY_SETTING_DEFINE(follytest, some_flag, std::string,"default","Description")
void setRemote(int value)
Definition: a.cpp:31
void forEachSetting(const std::function< void(const SettingMetadata &, StringPiece, StringPiece)> &func) const override
Definition: Settings.cpp:95
std::string b_func()
Definition: b.cpp:38
static const char *const value
Definition: Conv.cpp:50
if(FOLLY_USE_SYMBOLIZER) add_library(folly_exception_tracer_base ExceptionTracer.cpp StackTrace.cpp) apply_folly_compile_options_to_target(folly_exception_tracer_base) target_link_libraries(folly_exception_tracer_base PUBLIC folly) add_library(folly_exception_tracer ExceptionStackTraceLib.cpp ExceptionTracerLib.cpp) apply_folly_compile_options_to_target(folly_exception_tracer) target_link_libraries(folly_exception_tracer PUBLIC folly_exception_tracer_base) add_library(folly_exception_counter ExceptionCounterLib.cpp) apply_folly_compile_options_to_target(folly_exception_counter) target_link_libraries(folly_exception_counter PUBLIC folly_exception_tracer) install(FILES ExceptionAbi.h ExceptionCounterLib.h ExceptionTracer.h ExceptionTracerLib.h StackTrace.h DESTINATION $
Definition: CMakeLists.txt:1
#define FOLLY_SETTING(_project, _name)
Definition: Settings.h:192
Optional< SettingMetadata > getSettingsMeta(StringPiece settingName)
Definition: Settings.cpp:53
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
Optional< SettingsInfo > getAsString(StringPiece settingName) const override
Definition: Settings.cpp:75
const char * string
Definition: Conv.cpp:212
bool operator==(const UserDefinedType &other) const
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
int a_func()
Definition: a.cpp:26
bool resetToDefault(StringPiece settingName) override
Definition: Settings.cpp:85
TEST(Settings, user_defined)