1515 * See the License for the specific language governing
1616 * permissions and limitations under the License. */
1717
18- #include " flow/log/detail/component_cfg.hpp"
1918#include " flow/log/log.hpp"
19+ #include " flow/log/simple_ostream_logger.hpp"
20+ #include " flow/log/detail/component_cfg.hpp" // Yes, detail/ -- we do what we must.
2021#include " flow/test/test_logger.hpp"
2122#include " flow/perf/checkpt_timer.hpp"
2223#include " flow/util/string_view.hpp"
@@ -50,17 +51,18 @@ using Dict_val_b_hash_map = Component_payload_type_dict_by_val_via_b_hash_map<cf
5051using Dict_val_array = Component_payload_type_dict_by_val_via_array<cfg_t >;
5152using Dict_val_sorted_array = Component_payload_type_dict_by_val_via_sorted_array<cfg_t >;
5253
53- namespace n1 ::n1 { enum class Enum { S_A }; }
54- namespace n2 ::n2 { enum class Enum { S_A }; }
55- namespace n3 ::n3 { enum class Enum { S_A }; }
56- namespace n4 ::n4 { enum class Enum { S_A }; }
57- namespace n5 ::n5 { enum class Enum { S_A }; }
58- namespace n6 ::n6 { enum class Enum { S_A }; }
59- namespace n7 ::n7 { enum class Enum { S_A }; }
60- namespace n8 ::n8 { enum class Enum { S_A }; }
61- namespace n9 ::n9 { enum class Enum { S_A }; }
62- namespace n0 ::n0 { enum class Enum { S_A }; }
63- namespace nX ::nX { enum class Enum { S_A }; }
54+ namespace n1 ::n1 { enum class Cmps : Component::enum_raw_t { S_COMP_A, S_COMP_B }; }
55+ namespace n2 ::n2 { enum class Cmps : Component::enum_raw_t { S_COMP_A, S_COMP_B }; }
56+ namespace n3 ::n3 { enum class Cmps : Component::enum_raw_t { S_COMP_A, S_COMP_B }; }
57+ namespace n4 ::n4 { enum class Cmps : Component::enum_raw_t { S_COMP_A, S_COMP_B }; }
58+ namespace n5 ::n5 { enum class Cmps : Component::enum_raw_t { S_COMP_A, S_COMP_B }; }
59+ namespace n6 ::n6 { enum class Cmps : Component::enum_raw_t { S_COMP_A, S_COMP_B }; }
60+ namespace n7 ::n7 { enum class Cmps : Component::enum_raw_t { S_COMP_A, S_COMP_B }; }
61+ namespace n8 ::n8 { enum class Cmps : Component::enum_raw_t { S_COMP_A, S_COMP_B }; }
62+ namespace n9 ::n9 { enum class Cmps : Component::enum_raw_t { S_COMP_A, S_COMP_B }; }
63+ namespace n0 ::n0 { enum class Cmps : Component::enum_raw_t { S_COMP_A, S_COMP_B }; }
64+ namespace nX ::nX { enum class Cmps : Component::enum_raw_t { S_COMP_A, S_COMP_B }; }
65+ constexpr auto S_CMPS_SZ = static_cast <Component::enum_raw_t >(nX::nX::Cmps::S_COMP_B) + 1 ;
6466
6567String_view dict_type_printable (const std::type_index& type, bool brief = false )
6668{
@@ -108,16 +110,16 @@ void dict_map_death_test()
108110 {
109111 FLOW_LOG_INFO (" Testing dict-type [" << dict_type_printable (typeid (Dict)) << " ]." );
110112 Dict dict;
111- dict.insert (typeid (n1::n1::Enum ), 1 );
112- dict.insert (typeid (n0::n0::Enum ), 0 );
113- EXPECT_DEATH (dict.insert (typeid (n0::n0::Enum ), 0 ), " duplicate insertion is disallowed" );
114- EXPECT_DEATH (dict.insert (typeid (n0::n0::Enum ), -1 ), " duplicate insertion is disallowed" );
115- dict.insert (typeid (n2::n2::Enum ), 2 );
113+ dict.insert (typeid (n1::n1::Cmps ), 1 );
114+ dict.insert (typeid (n0::n0::Cmps ), 0 );
115+ EXPECT_DEATH (dict.insert (typeid (n0::n0::Cmps ), 0 ), " duplicate insertion is disallowed" );
116+ EXPECT_DEATH (dict.insert (typeid (n0::n0::Cmps ), -1 ), " duplicate insertion is disallowed" );
117+ dict.insert (typeid (n2::n2::Cmps ), 2 );
116118 cfg_t cfg;
117- EXPECT_TRUE (dict.lookup (typeid (n0::n0::Enum ), &cfg)); // Sanity checks.
118- EXPECT_TRUE (dict.lookup (typeid (n1::n1::Enum ), &cfg));
119- EXPECT_TRUE (dict.lookup (typeid (n2::n2::Enum ), &cfg));
120- EXPECT_FALSE (dict.lookup (typeid (n3::n3::Enum ), &cfg));
119+ EXPECT_TRUE (dict.lookup (typeid (n0::n0::Cmps ), &cfg)); // Sanity checks.
120+ EXPECT_TRUE (dict.lookup (typeid (n1::n1::Cmps ), &cfg));
121+ EXPECT_TRUE (dict.lookup (typeid (n2::n2::Cmps ), &cfg));
122+ EXPECT_FALSE (dict.lookup (typeid (n3::n3::Cmps ), &cfg));
121123 })(), ...);
122124}
123125
@@ -132,24 +134,24 @@ void dict_test()
132134 FLOW_LOG_INFO (" Testing dict-type [" << dict_type_printable (typeid (Dict)) << " ]." );
133135 {
134136 Dict dict;
135- dict.insert (typeid (n1::n1::Enum ), 1 );
136- dict.insert (typeid (n0::n0::Enum ), 0 );
137- dict.insert (typeid (n2::n2::Enum ), 2 );
138- dict.insert (typeid (nX::nX::Enum ), 100 );
137+ dict.insert (typeid (n1::n1::Cmps ), 1 );
138+ dict.insert (typeid (n0::n0::Cmps ), 0 );
139+ dict.insert (typeid (n2::n2::Cmps ), 2 );
140+ dict.insert (typeid (nX::nX::Cmps ), 100 );
139141 cfg_t cfg{-1 };
140- EXPECT_FALSE (dict.lookup (typeid (n3::n3::Enum ), &cfg));
142+ EXPECT_FALSE (dict.lookup (typeid (n3::n3::Cmps ), &cfg));
141143 EXPECT_EQ (cfg, -1 );
142- EXPECT_TRUE (dict.lookup (typeid (n0::n0::Enum ), &cfg));
144+ EXPECT_TRUE (dict.lookup (typeid (n0::n0::Cmps ), &cfg));
143145 EXPECT_EQ (cfg, 0 );
144- EXPECT_TRUE (dict.lookup (typeid (n1::n1::Enum ), &cfg));
146+ EXPECT_TRUE (dict.lookup (typeid (n1::n1::Cmps ), &cfg));
145147 EXPECT_EQ (cfg, 1 );
146- EXPECT_TRUE (dict.lookup (typeid (n2::n2::Enum ), &cfg));
148+ EXPECT_TRUE (dict.lookup (typeid (n2::n2::Cmps ), &cfg));
147149 EXPECT_EQ (cfg, 2 );
148- EXPECT_FALSE (dict.lookup (typeid (n3::n3::Enum ), &cfg));
150+ EXPECT_FALSE (dict.lookup (typeid (n3::n3::Cmps ), &cfg));
149151 EXPECT_EQ (cfg, 2 );
150- EXPECT_TRUE (dict.lookup (typeid (n0::n0::Enum ), &cfg));
152+ EXPECT_TRUE (dict.lookup (typeid (n0::n0::Cmps ), &cfg));
151153 EXPECT_EQ (cfg, 0 );
152- EXPECT_TRUE (dict.lookup (typeid (nX::nX::Enum ), &cfg));
154+ EXPECT_TRUE (dict.lookup (typeid (nX::nX::Cmps ), &cfg));
153155 EXPECT_EQ (cfg, 100 );
154156 /* @todo It is tough to test _by_val_ dudes where &typeid(X) yields different addrs at different times;
155157 * probably needs to be done across a shared-object boundary at least. Could contrive something though.
@@ -164,7 +166,7 @@ void dict_test()
164166 {
165167 Dict dict; // Deal with degenerate case of an empty dict.
166168 cfg_t cfg{-1 };
167- EXPECT_FALSE (dict.lookup (typeid (n0::n0::Enum ), &cfg));
169+ EXPECT_FALSE (dict.lookup (typeid (n0::n0::Cmps ), &cfg));
168170 EXPECT_EQ (cfg, -1 );
169171 }
170172 })(), ...);
@@ -191,18 +193,21 @@ void dict_benchmark(size_t n_cfgs)
191193 struct Type_rec { Ti m_type; cfg_t m_cfg; };
192194 vector<Type_rec> all_types =
193195 {
194- Type_rec{ &typeid (n1::n1::Enum ), 1 }, Type_rec{ &typeid (n2::n2::Enum ), 2 },
195- Type_rec{ &typeid (n3::n3::Enum ), 3 }, Type_rec{ &typeid (n4::n4::Enum ), 4 },
196- Type_rec{ &typeid (n5::n5::Enum ), 5 }, Type_rec{ &typeid (n6::n6::Enum ), 6 },
197- Type_rec{ &typeid (n7::n7::Enum ), 7 }, Type_rec{ &typeid (n8::n8::Enum ), 8 },
198- Type_rec{ &typeid (n9::n9::Enum ), 9 }, Type_rec{ &typeid (n0::n0::Enum ), 0 }
196+ Type_rec{ &typeid (n1::n1::Cmps ), 1 }, Type_rec{ &typeid (n2::n2::Cmps ), 2 },
197+ Type_rec{ &typeid (n3::n3::Cmps ), 3 }, Type_rec{ &typeid (n4::n4::Cmps ), 4 },
198+ Type_rec{ &typeid (n5::n5::Cmps ), 5 }, Type_rec{ &typeid (n6::n6::Cmps ), 6 },
199+ Type_rec{ &typeid (n7::n7::Cmps ), 7 }, Type_rec{ &typeid (n8::n8::Cmps ), 8 },
200+ Type_rec{ &typeid (n9::n9::Cmps ), 9 }, Type_rec{ &typeid (n0::n0::Cmps ), 0 }
199201 };
200202 EXPECT_TRUE (n_cfgs <= all_types.size ());
201203 all_types.resize (n_cfgs);
202204
203205 std::random_device rd; // Seed source.
204206 std::mt19937 gen (rd ());
205207 std::uniform_int_distribution<size_t > dist_to_n_cfgs (0 , n_cfgs - 1 );
208+ perf::Clock_types_subset clocks;
209+ constexpr auto CLK_TYPE = size_t (perf::Clock_type::S_CPU_THREAD_TOTAL_HI_RES);
210+ clocks.set (CLK_TYPE);
206211
207212 /* Maps Dict_* type to total (findable lookup + unfindable lookup) benchmark result for that dictionary impl.
208213 * Note: Empirically we see (as of this writing in the ~3 types of hardware tried) that the failed-lookup and
@@ -229,7 +234,7 @@ void dict_benchmark(size_t n_cfgs)
229234 {
230235 std::shuffle (all_types.begin (), all_types.end (), gen);
231236
232- const Ti unfindable_type = &typeid (nX::nX::Enum );
237+ const Ti unfindable_type = &typeid (nX::nX::Cmps );
233238 const auto & findable_type_rec = all_types[dist_to_n_cfgs (gen)];
234239 const Ti findable_type = findable_type_rec.m_type ;
235240 const auto findable_cfg = findable_type_rec.m_cfg ;
@@ -242,7 +247,7 @@ void dict_benchmark(size_t n_cfgs)
242247 dict.insert (*type.m_type , type.m_cfg );
243248 }
244249
245- const auto timer = boost::make_shared<Timer>(nullptr , " benchiez" , Timer::real_clock_types () , 2 );
250+ const auto timer = boost::make_shared<Timer>(nullptr , " benchiez" , clocks , 2 );
246251 dict.lookup (*unfindable_type, &cfg_found1);
247252 timer->checkpoint (" unfindable" );
248253 dict.lookup (*findable_type, &cfg_found2);
@@ -262,7 +267,6 @@ void dict_benchmark(size_t n_cfgs)
262267#endif
263268 // We can print out a pithy thing ourselves. (Also see above re. why we choose to use the sum.)
264269 const auto total_timer = timer_agg.create_aggregated_result (nullptr , false , 1 );
265- constexpr auto CLK_TYPE = size_t (perf::Clock_type::S_REAL_HI_RES);
266270 const Fine_duration time = total_timer->since_start ().m_values [CLK_TYPE];
267271 const Fine_duration time1 = total_timer->checkpoints ()[0 ].m_since_last .m_values [CLK_TYPE];
268272#if 0 // We'll summarize even more pithily below by showing: (time) = (time1) + (time - time1).
@@ -447,9 +451,35 @@ TEST(Component_cfg_test, Dict_internals_benchmark)
447451 }
448452}
449453
454+ /* While Dict_internals_interface tests the nitty-gritty of the map lookup at the heart of it -- which due to
455+ * perf matters has much subtlety to it -- this tests it end-to-end through the publicly available log::Config API. */
450456TEST (Component_cfg_test, Interface)
451457{
452- // @todo Add.
453- }
458+ #if 0
459+ Config cfg(Sev::S_INFO);
460+ cfg.init_component_to_union_idx_mapping<>
461+ (10,
462+ S_CMPS_SZ, // @todo Test subtleties of this arg.
463+ true);
464+
465+ Component comp0a{n0::n0::Cmps::S_COMP_A};
466+ Component comp0b{n0::n0::Cmps::S_COMP_B};
467+ Component comp1a{n1::n1::Cmps::S_COMP_A};
468+ Component comp1b{n1::n1::Cmps::S_COMP_B};
469+
454470
471+
472+
473+ /* @todo Test component names (config via component-name Config::configure_component_verbosity_by_name();
474+ * output of component-names Config::output_component_to_ostream(); the relevant Config::init_*()).
475+ * (Originally unit-test was created in the first place due to the Component_payload_type_dict_... work;
476+ * but as of this writing the other aspects of per-component log::Config remain un-unit-tested, though they
477+ * have long been verified via heavy use + functional tests. Obv the point of unit tests = do better than that.) */
478+
479+ /* @todo Test various `Logger`s and/or Ostream_log_msg_writer in the sense that they leverage component-based
480+ * log::Config aspects. I.e., test from a still-higher layer. Possibly that would go in the unit tests
481+ * for those classes though. As of this writing they don't exist. */
482+ #endif
483+
484+ } // TEST(Component_cfg_test, Interface)
455485} // namespace flow::log::test
0 commit comments