Skip to content

Commit 56d00b2

Browse files
authored
Feature/misc helpers (#101)
* + Algorithms.MinMax * EnumHelper cleanup * GetDefinedFlags to normal static method * Update test * Fixes on review
1 parent 03235d5 commit 56d00b2

9 files changed

Lines changed: 1083 additions & 268 deletions

File tree

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
using System;
2+
using System.Linq;
3+
4+
using NUnit.Framework;
5+
6+
namespace CodeJam
7+
{
8+
[TestFixture]
9+
public class MinMaxTest
10+
{
11+
public struct Comparable : IComparable
12+
{
13+
public Comparable(int value)
14+
{
15+
Value = value;
16+
}
17+
18+
public int Value { get; }
19+
20+
#region Implementation of IComparable
21+
public int CompareTo(object obj)
22+
{
23+
if (!(obj is Comparable other)) return 1;
24+
25+
return Value.CompareTo(other.Value);
26+
}
27+
#endregion
28+
}
29+
30+
[Test]
31+
public static void TestMinMaxTrivial()
32+
{
33+
var c1 = 1M;
34+
var c2 = 2M;
35+
36+
Assert.AreEqual(c1, Algorithms.Min(c1, c2));
37+
Assert.AreEqual(c1, Algorithms.Min(c2, c1));
38+
Assert.AreEqual(c2, Algorithms.Max(c1, c2));
39+
Assert.AreEqual(c2, Algorithms.Max(c2, c1));
40+
}
41+
42+
[Test]
43+
public static void TestMinMaxOverIComparable()
44+
{
45+
var c1 = new Comparable(1);
46+
var c2 = new Comparable(2);
47+
48+
Assert.AreEqual(c1, Algorithms.Min(c1, c2));
49+
Assert.AreEqual(c1, Algorithms.Min(c2, c1));
50+
Assert.AreEqual(c2, Algorithms.Max(c1, c2));
51+
Assert.AreEqual(c2, Algorithms.Max(c2, c1));
52+
}
53+
54+
[Test]
55+
public static void TestMinMaxOverNullable()
56+
{
57+
Comparable? c1 = new Comparable(1);
58+
Comparable? cMinus1 = new Comparable(-1);
59+
Comparable? c2 = new Comparable(2);
60+
61+
Assert.AreEqual(c1, Algorithms.Min(c1, c2));
62+
Assert.AreEqual(c1, Algorithms.Min(c2, c1));
63+
Assert.AreEqual(c2, Algorithms.Max(c1, c2));
64+
Assert.AreEqual(c2, Algorithms.Max(c2, c1));
65+
66+
Assert.AreEqual(null, Algorithms.Min(c1, null));
67+
Assert.AreEqual(null, Algorithms.Min(null, c1));
68+
Assert.AreEqual(c1, Algorithms.Max(null, c1));
69+
Assert.AreEqual(c1, Algorithms.Max(c1, null));
70+
71+
Assert.AreEqual(null, Algorithms.Min(cMinus1, null));
72+
Assert.AreEqual(null, Algorithms.Min(null, cMinus1));
73+
Assert.AreEqual(cMinus1, Algorithms.Max(null, cMinus1));
74+
Assert.AreEqual(cMinus1, Algorithms.Max(cMinus1, null));
75+
}
76+
77+
[Test]
78+
public static void TestMinMaxOverNullableEnum()
79+
{
80+
ConsoleColor? c1 = (ConsoleColor)1;
81+
ConsoleColor? cMinus1 = (ConsoleColor)(-1);
82+
ConsoleColor? c2 = (ConsoleColor)2;
83+
84+
Assert.AreEqual(c1, Algorithms.Min(c1, c2));
85+
Assert.AreEqual(c1, Algorithms.Min(c2, c1));
86+
Assert.AreEqual(c2, Algorithms.Max(c1, c2));
87+
Assert.AreEqual(c2, Algorithms.Max(c2, c1));
88+
89+
Assert.AreEqual(null, Algorithms.Min(c1, null));
90+
Assert.AreEqual(null, Algorithms.Min(null, c1));
91+
Assert.AreEqual(c1, Algorithms.Max(null, c1));
92+
Assert.AreEqual(c1, Algorithms.Max(c1, null));
93+
94+
Assert.AreEqual(null, Algorithms.Min(cMinus1, null));
95+
Assert.AreEqual(null, Algorithms.Min(null, cMinus1));
96+
Assert.AreEqual(cMinus1, Algorithms.Max(null, cMinus1));
97+
Assert.AreEqual(cMinus1, Algorithms.Max(cMinus1, null));
98+
}
99+
}
100+
}

CodeJam.Main.Tests/Assertions/EnumCodeTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public void TestDebugDefined()
4242
[Test]
4343
public void TestFlagsDefined()
4444
{
45-
var allDefinedFlags = EnumHelper.GetFlagsMask<BindingFlags>();
45+
var allDefinedFlags = EnumHelper.GetValuesMask<BindingFlags>();
4646
// ReSharper disable once RedundantCast
4747
var allFlags = (BindingFlags)(int)-1;
4848
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => EnumCode.FlagsDefined(allFlags, "arg00"));

CodeJam.Main.Tests/EnumHelperTests.cs

Lines changed: 88 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
using CodeJam.Arithmetic;
77
using CodeJam.Strings;
88

9+
using JetBrains.Annotations;
10+
911
using NUnit.Framework;
1012

1113
using static NUnit.Framework.Assert;
@@ -31,16 +33,20 @@ private enum Flags : byte
3133
{
3234
Zero = 0x0,
3335
A = 0x1,
36+
[UsedImplicitly]
37+
ACopy = 0x1,
3438
B = 0x2,
3539
C = 0x4,
3640
D = 0x8,
3741
// ReSharper disable once InconsistentNaming
38-
CD = C | D
42+
CD = C | D,
43+
Dx = D | 0x20
3944
}
4045

4146
private const Flags Ab = Flags.A | Flags.B;
4247
private const Flags Abc = Flags.A | Flags.B | Flags.C;
4348
private const Flags Abcd = Flags.A | Flags.B | Flags.C | Flags.D;
49+
private const Flags Abcdx = Flags.A | Flags.B | Flags.C | Flags.D | Flags.Dx;
4450
private const Flags Bc = Flags.B | Flags.C;
4551
private const Flags Bd = Flags.B | Flags.D;
4652
private const Flags D = Flags.D;
@@ -64,6 +70,7 @@ private enum NoFlags : byte
6470
// ReSharper disable BitwiseOperatorOnEnumWithoutFlags
6571
private const NoFlags Ef = NoFlags.E | NoFlags.F;
6672
private const NoFlags Efg = NoFlags.E | NoFlags.F | NoFlags.G;
73+
private const NoFlags Efgh = NoFlags.E | NoFlags.F | NoFlags.G | NoFlags.H;
6774

6875
private const NoFlags NoFlagsUndef = (NoFlags)0x10;
6976

@@ -83,7 +90,7 @@ public enum NameDescEnum
8390
#endregion
8491

8592
[Test]
86-
public void Test0001IsDefined()
93+
public void TestIsDefined()
8794
{
8895
Throws<ArgumentException>(() => Enum.IsDefined(typeof(int), 2));
8996

@@ -126,20 +133,23 @@ public void Test0001IsDefined()
126133
[TestCase("C", ExpectedResult = true)]
127134
[TestCase("CD", ExpectedResult = true)]
128135
[TestCase("Undef", ExpectedResult = false)]
129-
public bool IsDefinedStr(string value) => EnumHelper.IsDefined<Flags>(value);
136+
public bool TestIsDefinedStr(string value) => EnumHelper.IsDefined<Flags>(value);
130137

131138
[Test]
132-
public void Test0002FlagsVsNoFlags()
139+
public void TestFlagsVsNoFlags()
133140
{
134141
IsTrue(EnumHelper.IsFlagsEnum<Flags>());
135142
IsFalse(EnumHelper.IsFlagsEnum<NoFlags>());
136143

137-
AreEqual(EnumHelper.GetFlagsMask<Flags>(), Abcd);
138-
AreEqual(EnumHelper.GetFlagsMask<NoFlags>(), NoFlags.Zero);
144+
AreEqual(EnumHelper.GetValuesMask<Flags>(), Abcdx);
145+
AreEqual(EnumHelper.GetValuesMask<NoFlags>(), Efgh);
146+
147+
IsTrue(EnumHelper.AreFlagsDefined(Abc));
148+
IsFalse(EnumHelper.AreFlagsDefined(Efg));
139149
}
140150

141151
[Test]
142-
public void Test01Parse()
152+
public void TestParse()
143153
{
144154
Flags result1;
145155
Flags result2;
@@ -182,31 +192,31 @@ public void Test01Parse()
182192
}
183193

184194
[Test]
185-
public void Test02GetName() => AreEqual("ReturnValue", EnumHelper.GetName(AttributeTargets.ReturnValue));
195+
public void TestGetName() => AreEqual("ReturnValue", EnumHelper.GetName(AttributeTargets.ReturnValue));
186196

187197
[Test]
188-
public void Test03GetNames() =>
198+
public void TestGetNames() =>
189199
AreEqual(
190200
"Assembly, Module, Class, Struct, Enum, Constructor, Method, Property, Field, Event, Interface, Parameter, " +
191201
"Delegate, ReturnValue, GenericParameter, All",
192202
EnumHelper.GetNames<AttributeTargets>().Join(", "));
193203

194204
[Test]
195-
public void Test04GetValues() =>
205+
public void TestGetValues() =>
196206
AreEqual(
197207
"Assembly, Module, Class, Struct, Enum, Constructor, Method, Property, Field, Event, Interface, Parameter, " +
198208
"Delegate, ReturnValue, GenericParameter, All",
199209
EnumHelper.GetValues<AttributeTargets>().Join(", "));
200210

201211
[Test]
202-
public void Test05GetNameValues() =>
212+
public void TestGetNameValues() =>
203213
AreEqual(
204214
"Assembly, Module, Class, Struct, Enum, Constructor, Method, Property, Field, Event, Interface, Parameter, " +
205215
"Delegate, ReturnValue, GenericParameter, All",
206216
EnumHelper.GetNameValues<AttributeTargets>().Select(kvp => kvp.Key).Join(", "));
207217

208218
[Test]
209-
public static void Test0601IsFlagSet()
219+
public static void TestIsFlagSet()
210220
{
211221
IsTrue(Abc.HasFlag(Zero));
212222
IsTrue(Abc.HasFlag(Bc));
@@ -244,10 +254,68 @@ public static void Test0601IsFlagSet()
244254
IsTrue(Abc.IsFlagUnset(D));
245255
}
246256

257+
[Test]
258+
public static void TestIsFlagSetNoFlags()
259+
{
260+
IsTrue(Efg.HasFlag(NoFlags.Zero));
261+
IsTrue(Efg.HasFlag(Ef));
262+
IsTrue(Efg.HasFlag(NoFlags.E));
263+
IsFalse(Efg.HasFlag(NoFlags.H));
264+
IsFalse(Efg.HasFlag(NoFlagsUndef));
265+
266+
IsTrue(Efg.IsFlagSet(NoFlags.Zero));
267+
IsTrue(Efg.IsFlagSet(Ef));
268+
IsTrue(Efg.IsFlagSet(NoFlags.E));
269+
IsFalse(Efg.IsFlagSet(NoFlags.H));
270+
IsFalse(Efg.IsFlagSet(NoFlagsUndef));
271+
272+
IsFalse(Efg.IsAnyFlagUnset(NoFlags.Zero));
273+
IsFalse(Efg.IsAnyFlagUnset(Ef));
274+
IsFalse(Efg.IsAnyFlagUnset(NoFlags.E));
275+
IsTrue(Efg.IsAnyFlagUnset(NoFlags.H));
276+
IsTrue(Efg.IsAnyFlagUnset(NoFlagsUndef));
277+
278+
IsTrue(Efg.IsAnyFlagSet(NoFlags.Zero));
279+
IsTrue(Efg.IsAnyFlagSet(Ef));
280+
IsTrue(Efg.IsAnyFlagSet(NoFlags.E));
281+
IsFalse(Efg.IsAnyFlagSet(NoFlags.H));
282+
IsFalse(Efg.IsAnyFlagSet(NoFlagsUndef));
283+
284+
IsFalse(Efg.IsFlagUnset(NoFlags.Zero));
285+
IsFalse(Efg.IsFlagUnset(Ef));
286+
IsFalse(Efg.IsFlagUnset(NoFlags.E));
287+
IsTrue(Efg.IsFlagUnset(NoFlags.H));
288+
IsTrue(Efg.IsFlagUnset(NoFlagsUndef));
289+
}
290+
291+
[Test]
292+
public static void TestToFlags()
293+
{
294+
AreEqual(Abcd.ToFlags(), new[] { Flags.A, Flags.B, Flags.C, Flags.D });
295+
AreEqual(Zero.ToFlags(), new Flags[] { });
296+
AreEqual(Undef.ToFlags(), new Flags[] { });
297+
AreEqual(Flags.Dx.ToFlags(), new[] { D, Flags.Dx });
298+
299+
AreEqual(NoFlags.E.ToFlags(), new[] { NoFlags.E });
300+
AreEqual(Efg.ToFlags(), new NoFlags[] { });
301+
}
302+
303+
[Test]
304+
public static void TestGetDefinedFlags()
305+
{
306+
AreEqual(EnumHelper.GetDefinedFlags(Abcd), new[] { Flags.A, Flags.B, Flags.C, Flags.D, Flags.CD });
307+
AreEqual(EnumHelper.GetDefinedFlags(Zero), new Flags[] { });
308+
AreEqual(EnumHelper.GetDefinedFlags(Undef), new Flags[] { });
309+
AreEqual(EnumHelper.GetDefinedFlags(Flags.Dx), new[] { D, Flags.Dx });
310+
311+
AreEqual(EnumHelper.GetDefinedFlags(NoFlags.E), new[] { NoFlags.E });
312+
AreEqual(EnumHelper.GetDefinedFlags(Efg), new NoFlags[] { });
313+
}
314+
247315
[Test]
248316
[SuppressMessage("ReSharper", "InconsistentNaming")]
249317
[SuppressMessage("ReSharper", "LocalVariableHidesMember")]
250-
public static void Test0602IsFlagSetOperators()
318+
public static void TestIsFlagSetOperators()
251319
{
252320
var isFlagSet = OperatorsFactory.IsFlagSetOperator<int>();
253321
var isAnyFlagSet = OperatorsFactory.IsAnyFlagSetOperator<int>();
@@ -276,7 +344,7 @@ public static void Test0602IsFlagSetOperators()
276344
[Test]
277345
[SuppressMessage("ReSharper", "InconsistentNaming")]
278346
[SuppressMessage("ReSharper", "LocalVariableHidesMember")]
279-
public static void Test0603IsFlagSetInt()
347+
public static void TestIsFlagSetInt()
280348
{
281349
bool IsFlagSet(int value, int flag) => (value & flag) == flag;
282350
bool IsAnyFlagSet(int value, int flag) => (flag == 0) || ((value & flag) != 0);
@@ -304,7 +372,7 @@ public static void Test0603IsFlagSetInt()
304372
}
305373

306374
[Test]
307-
public static void Test07SetFlag()
375+
public static void TestSetFlag()
308376
{
309377
AreEqual(Abc.SetFlag(Zero), Abc);
310378
AreEqual(Abc.SetFlag(Bc), Abc);
@@ -315,7 +383,7 @@ public static void Test07SetFlag()
315383
}
316384

317385
[Test]
318-
public static void Test08ClearFlag()
386+
public static void TestClearFlag()
319387
{
320388
AreEqual(Abc.ClearFlag(Zero), Abc);
321389
AreEqual(Abc.ClearFlag(Bc), Flags.A);
@@ -326,7 +394,7 @@ public static void Test08ClearFlag()
326394
}
327395

328396
[Test]
329-
public static void Test09SetOrClearFlag()
397+
public static void TestSetOrClearFlag()
330398
{
331399
AreEqual(Abc.SetFlag(Zero, true), Abc);
332400
AreEqual(Abc.SetFlag(Bc, true), Abc);
@@ -346,16 +414,16 @@ public static void Test09SetOrClearFlag()
346414
[TestCase(NameDescEnum.Field1, ExpectedResult = "Field 1")]
347415
[TestCase(NameDescEnum.Field2, ExpectedResult = "Field2")]
348416
[TestCase(NameDescEnum.Field3, ExpectedResult = "Field3")]
349-
public string GetDisplayName(NameDescEnum value) => EnumHelper.GetDisplayName(value);
417+
public string TestGetDisplayName(NameDescEnum value) => EnumHelper.GetDisplayName(value);
350418

351419
[TestCase(NameDescEnum.Field1, ExpectedResult = "Field 1 Desc")]
352420
[TestCase(NameDescEnum.Field2, ExpectedResult = null)]
353421
[TestCase(NameDescEnum.Field3, ExpectedResult = null)]
354-
public string GetDescription(NameDescEnum value) => EnumHelper.GetDescription(value);
422+
public string TestGetDescription(NameDescEnum value) => EnumHelper.GetDescription(value);
355423

356424
[TestCase(NameDescEnum.Field1, ExpectedResult = "Field 1 (Field 1 Desc)")]
357425
[TestCase(NameDescEnum.Field2, ExpectedResult = "Field2")]
358426
[TestCase(NameDescEnum.Field3, ExpectedResult = "Field3")]
359-
public string GetDisplay(NameDescEnum value) => EnumHelper.GetEnumValue(value).ToString();
427+
public string TestGetDisplay(NameDescEnum value) => EnumHelper.GetEnumValue(value).ToString();
360428
}
361429
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using CodeJam.Arithmetic;
2+
3+
using JetBrains.Annotations;
4+
5+
namespace CodeJam
6+
{
7+
partial class Algorithms
8+
{
9+
/// <summary>
10+
/// Compares two values and returns minimal one.
11+
/// </summary>
12+
/// <typeparam name="T">Type of the values.</typeparam>
13+
/// <param name="value1">Value 1.</param>
14+
/// <param name="value2">Value 2.</param>
15+
/// <returns>Minimal value.</returns>
16+
/// <remarks>
17+
/// Implementation is equivalent of
18+
/// <code>
19+
/// var min = value1 &lt;= value2 ? value1 : value2;
20+
/// </code>
21+
/// </remarks>
22+
[Pure]
23+
public static T Min<T>(T value1, T value2) => Operators<T>.Compare(value1, value2) <= 0 ? value1 : value2;
24+
25+
/// <summary>
26+
/// Compares two values and returns maximal one.
27+
/// </summary>
28+
/// <param name="value1">Value 1.</param>
29+
/// <param name="value2">Value 2.</param>
30+
/// <returns>Maximum value.</returns>
31+
/// <remarks>
32+
/// Implementation is equivalent of
33+
/// <code>
34+
/// var max = value1 &gt;= value2 ? value1 : value2;
35+
/// </code>
36+
/// </remarks>
37+
[Pure]
38+
public static T Max<T>(T value1, T value2) => Operators<T>.Compare(value1, value2) >= 0 ? value1 : value2;
39+
}
40+
}

0 commit comments

Comments
 (0)