@@ -82,3 +82,227 @@ TEST (FlagSetTests, From_String)
8282 EXPECT_EQ (noErrorLog, LogOption::fromString (" 01" ));
8383 EXPECT_EQ ((verboseLog | noErrorLog), LogOption::fromString (" 11" ));
8484}
85+
86+ TEST (FlagSetTests, DeclareValue)
87+ {
88+ constexpr auto value1 = LogOption::declareValue<Detail::verboseLog>();
89+ constexpr auto value2 = LogOption::declareValue<Detail::noErrorLog>();
90+ constexpr auto valueBoth = LogOption::declareValue<Detail::verboseLog, Detail::noErrorLog>();
91+
92+ EXPECT_TRUE (value1.test (verboseLog));
93+ EXPECT_FALSE (value1.test (noErrorLog));
94+
95+ EXPECT_FALSE (value2.test (verboseLog));
96+ EXPECT_TRUE (value2.test (noErrorLog));
97+
98+ EXPECT_TRUE (valueBoth.test (verboseLog));
99+ EXPECT_TRUE (valueBoth.test (noErrorLog));
100+ }
101+
102+ TEST (FlagSetTests, SetMethod)
103+ {
104+ LogOption option;
105+ EXPECT_FALSE (option.test (verboseLog));
106+
107+ option.set (verboseLog);
108+ EXPECT_TRUE (option.test (verboseLog));
109+ EXPECT_FALSE (option.test (noErrorLog));
110+
111+ option.set (noErrorLog);
112+ EXPECT_TRUE (option.test (verboseLog));
113+ EXPECT_TRUE (option.test (noErrorLog));
114+ }
115+
116+ TEST (FlagSetTests, WithSet)
117+ {
118+ LogOption option = verboseLog;
119+ auto newOption = option.withSet (noErrorLog);
120+
121+ // Original unchanged
122+ EXPECT_TRUE (option.test (verboseLog));
123+ EXPECT_FALSE (option.test (noErrorLog));
124+
125+ // New has both
126+ EXPECT_TRUE (newOption.test (verboseLog));
127+ EXPECT_TRUE (newOption.test (noErrorLog));
128+ }
129+
130+ TEST (FlagSetTests, UnsetMethod)
131+ {
132+ LogOption option = verboseLog | noErrorLog;
133+ EXPECT_TRUE (option.test (verboseLog));
134+ EXPECT_TRUE (option.test (noErrorLog));
135+
136+ option.unset (verboseLog);
137+ EXPECT_FALSE (option.test (verboseLog));
138+ EXPECT_TRUE (option.test (noErrorLog));
139+
140+ option.unset (noErrorLog);
141+ EXPECT_FALSE (option.test (verboseLog));
142+ EXPECT_FALSE (option.test (noErrorLog));
143+ }
144+
145+ TEST (FlagSetTests, WithUnset)
146+ {
147+ LogOption option = verboseLog | noErrorLog;
148+ auto newOption = option.withUnset (verboseLog);
149+
150+ // Original unchanged
151+ EXPECT_TRUE (option.test (verboseLog));
152+ EXPECT_TRUE (option.test (noErrorLog));
153+
154+ // New has only noErrorLog
155+ EXPECT_FALSE (newOption.test (verboseLog));
156+ EXPECT_TRUE (newOption.test (noErrorLog));
157+ }
158+
159+ TEST (FlagSetTests, OperatorOrEquals)
160+ {
161+ LogOption option = verboseLog;
162+ option |= noErrorLog;
163+
164+ EXPECT_TRUE (option.test (verboseLog));
165+ EXPECT_TRUE (option.test (noErrorLog));
166+ }
167+
168+ TEST (FlagSetTests, OperatorAnd)
169+ {
170+ LogOption option1 = verboseLog | noErrorLog;
171+ LogOption option2 = verboseLog;
172+
173+ auto result = option1 & option2;
174+
175+ EXPECT_TRUE (result.test (verboseLog));
176+ EXPECT_FALSE (result.test (noErrorLog));
177+ }
178+
179+ TEST (FlagSetTests, OperatorAndEquals)
180+ {
181+ LogOption option1 = verboseLog | noErrorLog;
182+ LogOption option2 = verboseLog;
183+
184+ option1 &= option2;
185+
186+ EXPECT_TRUE (option1.test (verboseLog));
187+ EXPECT_FALSE (option1.test (noErrorLog));
188+ }
189+
190+ TEST (FlagSetTests, OperatorNot)
191+ {
192+ LogOption option = verboseLog;
193+ auto inverted = ~option;
194+
195+ // Inverted should NOT have verboseLog set in the first bit position
196+ // but will have other bits set (this is bitwise NOT)
197+ EXPECT_FALSE (inverted.test (verboseLog));
198+
199+ // Note: ~verboseLog will have noErrorLog bit set (and potentially others)
200+ EXPECT_TRUE (inverted.test (noErrorLog));
201+ }
202+
203+ TEST (FlagSetTests, SetMultipleFlags)
204+ {
205+ LogOption option;
206+ option.set (verboseLog);
207+ option.set (noErrorLog);
208+
209+ EXPECT_TRUE (option.test (verboseLog));
210+ EXPECT_TRUE (option.test (noErrorLog));
211+ }
212+
213+ TEST (FlagSetTests, UnsetAllFlags)
214+ {
215+ LogOption option = verboseLog | noErrorLog;
216+ option.unset (verboseLog | noErrorLog);
217+
218+ EXPECT_FALSE (option.test (verboseLog));
219+ EXPECT_FALSE (option.test (noErrorLog));
220+ }
221+
222+ TEST (FlagSetTests, ChainedWithSet)
223+ {
224+ LogOption option;
225+ auto result = option.withSet (verboseLog).withSet (noErrorLog);
226+
227+ EXPECT_TRUE (result.test (verboseLog));
228+ EXPECT_TRUE (result.test (noErrorLog));
229+ }
230+
231+ TEST (FlagSetTests, ChainedWithUnset)
232+ {
233+ LogOption option = verboseLog | noErrorLog;
234+ auto result = option.withUnset (verboseLog).withUnset (noErrorLog);
235+
236+ EXPECT_FALSE (result.test (verboseLog));
237+ EXPECT_FALSE (result.test (noErrorLog));
238+ }
239+
240+ TEST (FlagSetTests, CombineOperators)
241+ {
242+ LogOption option1 = verboseLog;
243+ LogOption option2 = noErrorLog;
244+
245+ auto combined = option1 | option2;
246+ EXPECT_TRUE (combined.test (verboseLog));
247+ EXPECT_TRUE (combined.test (noErrorLog));
248+
249+ auto intersected = combined & verboseLog;
250+ EXPECT_TRUE (intersected.test (verboseLog));
251+ EXPECT_FALSE (intersected.test (noErrorLog));
252+ }
253+
254+ TEST (FlagSetTests, ConstexprDeclareValue)
255+ {
256+ // Test that declareValue is constexpr
257+ constexpr LogOption value = LogOption::declareValue<Detail::verboseLog>();
258+ static_assert (value.test (verboseLog), " Should be compile-time constant" );
259+ }
260+
261+ TEST (FlagSetTests, ConstexprOperations)
262+ {
263+ // Test constexpr operations
264+ constexpr LogOption option1 = verboseLog;
265+ constexpr LogOption option2 = noErrorLog;
266+ constexpr LogOption combined = option1 | option2;
267+
268+ static_assert (combined.test (verboseLog), " Should work at compile time" );
269+ static_assert (combined.test (noErrorLog), " Should work at compile time" );
270+ }
271+
272+ TEST (FlagSetTests, AndOperatorReturnsIntersection)
273+ {
274+ LogOption all = verboseLog | noErrorLog;
275+ LogOption some = verboseLog;
276+
277+ auto intersection = all & some;
278+
279+ EXPECT_EQ (intersection, verboseLog);
280+ EXPECT_NE (intersection, noErrorLog);
281+ }
282+
283+ TEST (FlagSetTests, NotOperatorInverts)
284+ {
285+ LogOption option = defaultLog; // No flags set
286+ auto inverted = ~option;
287+
288+ // After inversion, should have flags set (exact bits depend on type width)
289+ EXPECT_NE (inverted, option);
290+ }
291+
292+ TEST (FlagSetTests, SetIdempotent)
293+ {
294+ LogOption option = verboseLog;
295+ option.set (verboseLog); // Set same flag again
296+
297+ EXPECT_TRUE (option.test (verboseLog));
298+ EXPECT_EQ (option, verboseLog);
299+ }
300+
301+ TEST (FlagSetTests, UnsetIdempotent)
302+ {
303+ LogOption option;
304+ option.unset (verboseLog); // Unset flag that isn't set
305+
306+ EXPECT_FALSE (option.test (verboseLog));
307+ EXPECT_EQ (option, defaultLog);
308+ }
0 commit comments