trackler 2.0.8.24 → 2.0.8.26

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/tracks/c/config.json +9 -0
  4. data/tracks/c/exercises/nucleotide-count/makefile +15 -0
  5. data/tracks/c/exercises/nucleotide-count/src/example.c +43 -0
  6. data/tracks/c/exercises/nucleotide-count/src/example.h +6 -0
  7. data/tracks/c/exercises/nucleotide-count/test/test_nucleotide_count.c +58 -0
  8. data/tracks/c/exercises/nucleotide-count/test/vendor/unity.c +1300 -0
  9. data/tracks/c/exercises/nucleotide-count/test/vendor/unity.h +274 -0
  10. data/tracks/c/exercises/nucleotide-count/test/vendor/unity_internals.h +701 -0
  11. data/tracks/ceylon/README.md +2 -2
  12. data/tracks/csharp/.gitattributes +11 -0
  13. data/tracks/csharp/appveyor.yml +1 -4
  14. data/tracks/csharp/exercises/acronym/AcronymTest.cs +1 -1
  15. data/tracks/csharp/exercises/atbash-cipher/AtbashCipher.cs +8 -3
  16. data/tracks/csharp/exercises/atbash-cipher/AtbashCipherTest.cs +76 -0
  17. data/tracks/csharp/exercises/atbash-cipher/Example.cs +22 -23
  18. data/tracks/csharp/exercises/isogram/Example.cs +2 -2
  19. data/tracks/csharp/exercises/isogram/IsogramTest.cs +47 -15
  20. data/tracks/csharp/exercises/nth-prime/Example.cs +4 -1
  21. data/tracks/csharp/exercises/nth-prime/NthPrime.cs +1 -1
  22. data/tracks/csharp/exercises/nth-prime/NthPrimeTest.cs +29 -15
  23. data/tracks/csharp/exercises/perfect-numbers/Example.cs +14 -16
  24. data/tracks/csharp/exercises/perfect-numbers/PerfectNumbers.cs +2 -2
  25. data/tracks/csharp/exercises/perfect-numbers/PerfectNumbersTest.cs +78 -26
  26. data/tracks/csharp/exercises/pig-latin/PigLatinTest.cs +69 -24
  27. data/tracks/csharp/exercises/raindrops/Example.cs +1 -1
  28. data/tracks/csharp/exercises/raindrops/RaindropsTest.cs +93 -31
  29. data/tracks/csharp/exercises/roman-numerals/HINTS.md +2 -0
  30. data/tracks/csharp/exercises/roman-numerals/RomanNumeralsTest.cs +106 -23
  31. data/tracks/csharp/exercises/word-search/HINTS.md +6 -0
  32. data/tracks/csharp/generators/{TestClass.cs → Classes/TestClass.cs} +2 -1
  33. data/tracks/csharp/generators/{TestClassNameTransformer.cs → Classes/TestClassNameTransformer.cs} +1 -1
  34. data/tracks/csharp/generators/{TestClassRenderer.cs → Classes/TestClassRenderer.cs} +2 -1
  35. data/tracks/csharp/generators/Classes/TestedClassNameTransformer.cs +9 -0
  36. data/tracks/csharp/generators/{CanonicalData.cs → Data/CanonicalData.cs} +1 -1
  37. data/tracks/csharp/generators/{CanonicalDataCase.cs → Data/CanonicalDataCase.cs} +3 -3
  38. data/tracks/csharp/generators/{CanonicalDataCaseJsonConverter.cs → Data/CanonicalDataCaseJsonConverter.cs} +1 -1
  39. data/tracks/csharp/generators/{CanonicalDataCasesJsonConverter.cs → Data/CanonicalDataCasesJsonConverter.cs} +2 -2
  40. data/tracks/csharp/generators/{CanonicalDataParser.cs → Data/CanonicalDataParser.cs} +5 -5
  41. data/tracks/csharp/generators/{ExerciseCollection.cs → Data/ExerciseCollection.cs} +3 -3
  42. data/tracks/csharp/generators/Exercises/AcronymExercise.cs +20 -0
  43. data/tracks/csharp/generators/Exercises/AtbashCipherExercise.cs +20 -0
  44. data/tracks/csharp/generators/Exercises/BooleanExercise.cs +14 -0
  45. data/tracks/csharp/generators/Exercises/EqualityExercise.cs +14 -0
  46. data/tracks/csharp/generators/Exercises/Exercise.cs +59 -4
  47. data/tracks/csharp/generators/Exercises/IsogramExercise.cs +9 -0
  48. data/tracks/csharp/generators/Exercises/LeapExercise.cs +1 -4
  49. data/tracks/csharp/generators/Exercises/NthPrimeExercise.cs +25 -0
  50. data/tracks/csharp/generators/Exercises/PerfectNumbersExercise.cs +29 -0
  51. data/tracks/csharp/generators/Exercises/PigLatinExercise.cs +9 -0
  52. data/tracks/csharp/generators/Exercises/RaindropsExercise.cs +20 -0
  53. data/tracks/csharp/generators/Exercises/RomanNumeralsExercise.cs +30 -0
  54. data/tracks/csharp/generators/Helpers/StringExtensions.cs +8 -0
  55. data/tracks/csharp/generators/{To.cs → Helpers/To.cs} +4 -1
  56. data/tracks/csharp/generators/Methods/BooleanTestMethodGenerator.cs +32 -0
  57. data/tracks/csharp/generators/Methods/EqualityTestMethodGenerator.cs +25 -0
  58. data/tracks/csharp/generators/Methods/ExceptionTestMethodGenerator.cs +30 -0
  59. data/tracks/csharp/generators/{TestMethod.cs → Methods/TestMethod.cs} +6 -3
  60. data/tracks/csharp/generators/Methods/TestMethodData.cs +12 -0
  61. data/tracks/csharp/generators/Methods/TestMethodGenerator.cs +64 -0
  62. data/tracks/csharp/generators/Methods/TestMethodNameTransformer.cs +23 -0
  63. data/tracks/csharp/generators/Methods/TestMethodOptions.cs +13 -0
  64. data/tracks/csharp/generators/{TestMethodRenderer.cs → Methods/TestMethodRenderer.cs} +1 -1
  65. data/tracks/csharp/generators/{TestedMethodNameTransformer.cs → Methods/TestedMethodNameTransformer.cs} +1 -1
  66. data/tracks/csharp/generators/Methods/TestedMethodType.cs +9 -0
  67. data/tracks/csharp/generators/Program.cs +2 -0
  68. data/tracks/elixir/config.json +7 -0
  69. data/tracks/elixir/exercises/diffie-hellman/HINTS.md +10 -0
  70. data/tracks/elixir/exercises/diffie-hellman/diffie_hellman.exs +61 -0
  71. data/tracks/elixir/exercises/diffie-hellman/diffie_hellman_test.exs +99 -0
  72. data/tracks/elixir/exercises/diffie-hellman/example.exs +64 -0
  73. data/tracks/haskell/exercises/pov/src/POV.hs +2 -2
  74. data/tracks/haskell/exercises/pythagorean-triplet/src/Triplet.hs +6 -3
  75. data/tracks/haskell/exercises/queen-attack/src/Queens.hs +1 -1
  76. data/tracks/haskell/exercises/raindrops/src/Raindrops.hs +2 -1
  77. data/tracks/haskell/exercises/robot-name/src/Robot.hs +2 -2
  78. data/tracks/haskell/exercises/robot-simulator/src/Robot.hs +6 -6
  79. data/tracks/haskell/exercises/roman-numerals/src/Roman.hs +2 -1
  80. data/tracks/haskell/exercises/run-length-encoding/src/RunLength.hs +2 -2
  81. data/tracks/haskell/exercises/saddle-points/src/Matrix.hs +2 -1
  82. data/tracks/haskell/exercises/say/src/Say.hs +2 -1
  83. data/tracks/haskell/exercises/scrabble-score/src/Scrabble.hs +4 -2
  84. data/tracks/haskell/exercises/secret-handshake/src/SecretHandshake.hs +1 -1
  85. data/tracks/haskell/exercises/sgf-parsing/src/Sgf.hs +1 -1
  86. data/tracks/java/exercises/acronym/src/example/java/Acronym.java +11 -1
  87. data/tracks/java/exercises/acronym/src/test/java/AcronymTest.java +8 -9
  88. data/tracks/java/exercises/grade-school/src/test/java/SchoolTest.java +8 -2
  89. data/tracks/java/exercises/luhn/src/test/java/LuhnValidatorTest.java +20 -13
  90. data/tracks/java/exercises/robot-name/src/test/java/RobotTest.java +6 -1
  91. data/tracks/javascript/README.md +1 -1
  92. data/tracks/javascript/docs/TESTS.md +9 -1
  93. data/tracks/kotlin/exercises/luhn/src/example/kotlin/Luhn.kt +18 -26
  94. data/tracks/kotlin/exercises/luhn/src/test/kotlin/LuhnTest.kt +40 -38
  95. data/tracks/php/README.md +1 -1
  96. data/tracks/php/config.json +5 -0
  97. data/tracks/php/exercises/perfect-numbers/example.php +23 -0
  98. data/tracks/php/exercises/perfect-numbers/perfect-numbers_test.php +99 -0
  99. data/tracks/purescript/.travis.yml +1 -0
  100. data/tracks/purescript/bin/test.sh +33 -8
  101. data/tracks/purescript/config.json +7 -0
  102. data/tracks/purescript/exercises/meetup/bower.json +17 -0
  103. data/tracks/purescript/exercises/meetup/examples/src/Meetup.purs +37 -0
  104. data/tracks/purescript/exercises/meetup/src/Meetup.purs +11 -0
  105. data/tracks/purescript/exercises/meetup/test/Main.purs +395 -0
  106. data/tracks/python/README.md +7 -6
  107. data/tracks/python/docs/TOOLS.md +3 -3
  108. data/tracks/python/exercises/bracket-push/bracket_push_test.py +32 -15
  109. data/tracks/python/exercises/hamming/hamming_test.py +2 -0
  110. data/tracks/python/exercises/luhn/luhn_test.py +2 -0
  111. data/tracks/python/test/check-exercises.py +7 -1
  112. metadata +56 -20
  113. data/tracks/csharp/exercises/atbash-cipher/AtbashTest.cs +0 -17
  114. data/tracks/csharp/generators/BooleanTestMethod.cs +0 -36
  115. data/tracks/csharp/generators/TestMethodNameTransformer.cs +0 -11
  116. data/tracks/csharp/generators/TestedClassNameTransformer.cs +0 -11
  117. data/tracks/java/exercises/allergies/src/main/java/.keep +0 -0
@@ -1,10 +1,20 @@
1
- using System.Linq;
1
+ using System.Collections.Generic;
2
+ using System.Linq;
3
+ using Generators.Classes;
4
+ using Generators.Data;
5
+ using Generators.Methods;
2
6
  using Humanizer;
7
+ using Newtonsoft.Json.Linq;
8
+ using To = Generators.Helpers.To;
3
9
 
4
10
  namespace Generators.Exercises
5
11
  {
6
12
  public abstract class Exercise
7
13
  {
14
+ private static readonly BooleanTestMethodGenerator BooleanTestMethodGenerator = new BooleanTestMethodGenerator();
15
+ private static readonly EqualityTestMethodGenerator EqualityTestMethodGenerator = new EqualityTestMethodGenerator();
16
+ private static readonly ExceptionTestMethodGenerator ExceptionTestMethodGenerator = new ExceptionTestMethodGenerator();
17
+
8
18
  protected Exercise(string name)
9
19
  {
10
20
  Name = name;
@@ -14,12 +24,57 @@ namespace Generators.Exercises
14
24
 
15
25
  public TestClass CreateTestClass(CanonicalData canonicalData)
16
26
  {
17
- return new TestClass
27
+ var testClass = new TestClass
18
28
  {
19
29
  ClassName = Name.Transform(To.TestClassName),
20
- TestMethods = canonicalData.Cases.Select((canonicalDataCase, index) => CreateTestMethod(canonicalData, canonicalDataCase, index)).ToArray()
30
+ TestMethods = CreateTestMethods(canonicalData).ToArray()
21
31
  };
32
+
33
+ AddTestMethodUsingNamespaces(testClass);
34
+
35
+ return testClass;
36
+ }
37
+
38
+ private static void AddTestMethodUsingNamespaces(TestClass testClass)
39
+ {
40
+ foreach (var testMethod in testClass.TestMethods)
41
+ testClass.UsingNamespaces.UnionWith(testMethod.UsingNamespaces);
42
+ }
43
+
44
+ protected abstract TestMethod CreateTestMethod(TestMethodData testMethodData);
45
+
46
+ protected virtual IEnumerable<TestMethod> CreateTestMethods(CanonicalData canonicalData)
47
+ => canonicalData.Cases.Select((t, i) => CreateTestMethod(canonicalData, t, i));
48
+
49
+ protected virtual TestMethod CreateTestMethod(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index)
50
+ {
51
+ var testMethodData = CreateTestMethodData(canonicalData, canonicalDataCase, index);
52
+
53
+ if (testMethodData.CanonicalDataCase.Expected is JObject jObject)
54
+ return CreateExceptionTestMethod(testMethodData);
55
+
56
+ return CreateTestMethod(testMethodData);
22
57
  }
23
- protected abstract TestMethod CreateTestMethod(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index);
58
+
59
+ protected virtual TestMethodData CreateTestMethodData(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index)
60
+ => new TestMethodData
61
+ {
62
+ CanonicalData = canonicalData,
63
+ CanonicalDataCase = canonicalDataCase,
64
+ Index = index,
65
+ Options = CreateTestMethodOptions(canonicalData, canonicalDataCase, index)
66
+ };
67
+
68
+ protected virtual TestMethodOptions CreateTestMethodOptions(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index)
69
+ => new TestMethodOptions();
70
+
71
+ protected virtual TestMethod CreateBooleanTestMethod(TestMethodData testMethodData)
72
+ => BooleanTestMethodGenerator.Create(testMethodData);
73
+
74
+ protected virtual TestMethod CreateEqualityTestMethod(TestMethodData testMethodData)
75
+ => EqualityTestMethodGenerator.Create(testMethodData);
76
+
77
+ protected virtual TestMethod CreateExceptionTestMethod(TestMethodData testMethodData)
78
+ => ExceptionTestMethodGenerator.Create(testMethodData);
24
79
  }
25
80
  }
@@ -0,0 +1,9 @@
1
+ namespace Generators.Exercises
2
+ {
3
+ public class IsogramExercise : BooleanExercise
4
+ {
5
+ public IsogramExercise() : base("isogram")
6
+ {
7
+ }
8
+ }
9
+ }
@@ -1,12 +1,9 @@
1
1
  namespace Generators.Exercises
2
2
  {
3
- public class LeapExercise : Exercise
3
+ public class LeapExercise : BooleanExercise
4
4
  {
5
5
  public LeapExercise() : base("leap")
6
6
  {
7
7
  }
8
-
9
- protected override TestMethod CreateTestMethod(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index)
10
- => new BooleanTestMethod(canonicalData, canonicalDataCase, index);
11
8
  }
12
9
  }
@@ -0,0 +1,25 @@
1
+ using System;
2
+ using Generators.Data;
3
+ using Generators.Methods;
4
+ using Humanizer;
5
+
6
+ namespace Generators.Exercises
7
+ {
8
+ public class NthPrimeExercise : EqualityExercise
9
+ {
10
+ public NthPrimeExercise() : base("nth-prime")
11
+ {
12
+ }
13
+
14
+ protected override TestMethod CreateTestMethod(TestMethodData testMethodData)
15
+ {
16
+ if (testMethodData.CanonicalDataCase.Expected is bool b)
17
+ {
18
+ testMethodData.Options.ExceptionType = typeof(ArgumentOutOfRangeException);
19
+ return CreateExceptionTestMethod(testMethodData);
20
+ }
21
+
22
+ return CreateEqualityTestMethod(testMethodData);
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,29 @@
1
+ using System;
2
+ using Generators.Data;
3
+ using Generators.Methods;
4
+ using Humanizer;
5
+
6
+ namespace Generators.Exercises
7
+ {
8
+ public class PerfectNumbersExercise : EqualityExercise
9
+ {
10
+ public PerfectNumbersExercise() : base("perfect-numbers")
11
+ {
12
+ }
13
+
14
+ protected override TestMethodData CreateTestMethodData(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index)
15
+ {
16
+ var testMethodData = base.CreateTestMethodData(canonicalData, canonicalDataCase, index);
17
+ testMethodData.Options.ExceptionType = typeof(ArgumentOutOfRangeException);
18
+ testMethodData.Options.FormatExpected = false;
19
+
20
+ if (testMethodData.CanonicalDataCase.Expected is string classificationType)
21
+ testMethodData.CanonicalDataCase.Expected = GetClassification(classificationType);
22
+
23
+ return testMethodData;
24
+ }
25
+
26
+ private static string GetClassification(string classificationType)
27
+ => $"Classification.{classificationType.Transform(Humanizer.To.TitleCase)}";
28
+ }
29
+ }
@@ -0,0 +1,9 @@
1
+ namespace Generators.Exercises
2
+ {
3
+ public class PigLatinExercise : EqualityExercise
4
+ {
5
+ public PigLatinExercise() : base("pig-latin")
6
+ {
7
+ }
8
+ }
9
+ }
@@ -0,0 +1,20 @@
1
+ using Generators.Data;
2
+ using Generators.Methods;
3
+
4
+ namespace Generators.Exercises
5
+ {
6
+ public class RaindropsExercise : EqualityExercise
7
+ {
8
+ public RaindropsExercise() : base("raindrops")
9
+ {
10
+ }
11
+
12
+ protected override TestMethodOptions CreateTestMethodOptions(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index)
13
+ {
14
+ var testMethodOptions = base.CreateTestMethodOptions(canonicalData, canonicalDataCase, index);
15
+ testMethodOptions.InputProperty = "number";
16
+
17
+ return testMethodOptions;
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,30 @@
1
+ using Generators.Data;
2
+ using Generators.Methods;
3
+
4
+ namespace Generators.Exercises
5
+ {
6
+ public class RomanNumeralsExercise : EqualityExercise
7
+ {
8
+ public RomanNumeralsExercise() : base("roman-numerals")
9
+ {
10
+ }
11
+
12
+ protected override TestMethodData CreateTestMethodData(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index)
13
+ {
14
+ var testMethodData = base.CreateTestMethodData(canonicalData, canonicalDataCase, index);
15
+ testMethodData.CanonicalDataCase.Property = "ToRoman";
16
+ testMethodData.CanonicalDataCase.Description = "Number_" + testMethodData.CanonicalDataCase.Description;
17
+
18
+ return testMethodData;
19
+ }
20
+
21
+ protected override TestMethodOptions CreateTestMethodOptions(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index)
22
+ {
23
+ var testMethodOptions = new TestMethodOptions();
24
+ testMethodOptions.InputProperty = "number";
25
+ testMethodOptions.TestedMethodType = TestedMethodType.Extension;
26
+
27
+ return testMethodOptions;
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,8 @@
1
+ namespace Generators.Helpers
2
+ {
3
+ public static class StringExtensions
4
+ {
5
+ public static string EnsureStartsWith(this string str, string value)
6
+ => str.StartsWith(value) ? str : value + str;
7
+ }
8
+ }
@@ -1,4 +1,7 @@
1
- namespace Generators
1
+ using Generators.Classes;
2
+ using Generators.Methods;
3
+
4
+ namespace Generators.Helpers
2
5
  {
3
6
  public static class To
4
7
  {
@@ -0,0 +1,32 @@
1
+ using System;
2
+ using Generators.Helpers;
3
+
4
+ namespace Generators.Methods
5
+ {
6
+ public class BooleanTestMethodGenerator : TestMethodGenerator
7
+ {
8
+ protected override string Body
9
+ {
10
+ get
11
+ {
12
+ switch (TestMethodData.Options.TestedMethodType)
13
+ {
14
+ case TestedMethodType.Static:
15
+ return $"{Assertion}({TestedClassName}.{TestedMethod}({Input}));";
16
+ case TestedMethodType.Instance:
17
+ return $"var sut = new {TestedClassName}();\n {Assertion}(sut.{TestedMethod}({Input}));";
18
+ case TestedMethodType.Extension:
19
+ return $"{Assertion}({Input}.{TestedMethod}());";
20
+ default:
21
+ throw new ArgumentOutOfRangeException();
22
+ }
23
+ }
24
+ }
25
+
26
+ private string Assertion
27
+ => $"Assert.{Convert.ToBoolean(TestMethodData.CanonicalDataCase.Expected)}";
28
+
29
+ protected override string TestedMethod
30
+ => base.TestedMethod.EnsureStartsWith("Is");
31
+ }
32
+ }
@@ -0,0 +1,25 @@
1
+ using System;
2
+
3
+ namespace Generators.Methods
4
+ {
5
+ public class EqualityTestMethodGenerator : TestMethodGenerator
6
+ {
7
+ protected override string Body
8
+ {
9
+ get
10
+ {
11
+ switch (TestMethodData.Options.TestedMethodType)
12
+ {
13
+ case TestedMethodType.Static:
14
+ return $"Assert.Equal({Expected}, {TestedClassName}.{TestedMethod}({Input}));";
15
+ case TestedMethodType.Instance:
16
+ return $"var sut = new {TestedClassName}();\n Assert.Equal({Expected}, sut.{TestedMethod}({Input}));";
17
+ case TestedMethodType.Extension:
18
+ return $"Assert.Equal({Expected}, {Input}.{TestedMethod}());";
19
+ default:
20
+ throw new ArgumentOutOfRangeException();
21
+ }
22
+ }
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,30 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+
4
+ namespace Generators.Methods
5
+ {
6
+ public class ExceptionTestMethodGenerator : TestMethodGenerator
7
+ {
8
+ protected override string Body
9
+ {
10
+ get
11
+ {
12
+ switch (TestMethodData.Options.TestedMethodType)
13
+ {
14
+ case TestedMethodType.Static:
15
+ return $"Assert.Throws<{ExceptionType}>(() => {TestedClassName}.{TestedMethod}({Input}));";
16
+ case TestedMethodType.Instance:
17
+ return $"var sut = new {TestedClassName}();\n Assert.Throws<{ExceptionType}>(() => sut.{TestedMethod}({Input}));;";
18
+ case TestedMethodType.Extension:
19
+ return $"Assert.Throws<{ExceptionType}>(() => {Input}.{TestedMethod}());";
20
+ default:
21
+ throw new ArgumentOutOfRangeException();
22
+ }
23
+ }
24
+ }
25
+
26
+ protected override ISet<string> UsingNamespaces => new HashSet<string> { TestMethodData.Options.ExceptionType.Namespace };
27
+
28
+ protected virtual string ExceptionType => TestMethodData.Options.ExceptionType.Name;
29
+ }
30
+ }
@@ -1,9 +1,12 @@
1
- namespace Generators
1
+ using System.Collections.Generic;
2
+
3
+ namespace Generators.Methods
2
4
  {
3
5
  public class TestMethod
4
6
  {
5
- public int Index { get; set; }
7
+ public ISet<string> UsingNamespaces { get; set; } = new HashSet<string>();
6
8
  public string MethodName { get; set; }
7
9
  public string Body { get; set; }
10
+ public int Index { get; set; }
8
11
  }
9
- }
12
+ }
@@ -0,0 +1,12 @@
1
+ using Generators.Data;
2
+
3
+ namespace Generators.Methods
4
+ {
5
+ public class TestMethodData
6
+ {
7
+ public CanonicalData CanonicalData { get; set; }
8
+ public CanonicalDataCase CanonicalDataCase { get; set;}
9
+ public int Index { get; set; }
10
+ public TestMethodOptions Options { get; set; } = new TestMethodOptions();
11
+ }
12
+ }
@@ -0,0 +1,64 @@
1
+ using System.Collections.Generic;
2
+ using Humanizer;
3
+ using To = Generators.Helpers.To;
4
+
5
+ namespace Generators.Methods
6
+ {
7
+ public abstract class TestMethodGenerator
8
+ {
9
+ public TestMethod Create(TestMethodData testMethodData)
10
+ {
11
+ TestMethodData = testMethodData;
12
+
13
+ return new TestMethod
14
+ {
15
+ MethodName = MethodName,
16
+ Body = Body,
17
+ Index = TestMethodData.Index,
18
+ UsingNamespaces = UsingNamespaces
19
+ };
20
+ }
21
+
22
+ protected TestMethodData TestMethodData { get; private set; }
23
+
24
+ protected abstract string Body { get; }
25
+
26
+ protected virtual ISet<string> UsingNamespaces
27
+ => new HashSet<string>();
28
+
29
+ protected virtual string MethodName
30
+ => TestMethodData.CanonicalDataCase.Description.Replace(":", " is").Transform(To.TestMethodName);
31
+
32
+ protected virtual string TestedClassName
33
+ => TestMethodData.CanonicalData.Exercise.Transform(To.TestedClassName);
34
+
35
+ protected virtual string TestedMethod
36
+ => TestMethodData.CanonicalDataCase.Property.Transform(To.TestedMethodName);
37
+
38
+ protected virtual object Input =>
39
+ TestMethodData.Options.FormatInput
40
+ ? FormatValue(InputValue)
41
+ : InputValue;
42
+
43
+ protected virtual object Expected =>
44
+ TestMethodData.Options.FormatExpected
45
+ ? FormatValue(TestMethodData.CanonicalDataCase.Expected)
46
+ : TestMethodData.CanonicalDataCase.Expected;
47
+
48
+ protected virtual object InputValue
49
+ => TestMethodData.Options.InputProperty == null
50
+ ? TestMethodData.CanonicalDataCase.Input
51
+ : TestMethodData.CanonicalDataCase.Data[TestMethodData.Options.InputProperty];
52
+
53
+ protected virtual object FormatValue(object val)
54
+ {
55
+ switch (val)
56
+ {
57
+ case string s:
58
+ return $"\"{s}\"";
59
+ default:
60
+ return val;
61
+ }
62
+ }
63
+ }
64
+ }
@@ -0,0 +1,23 @@
1
+ using System.Text.RegularExpressions;
2
+ using Humanizer;
3
+
4
+ namespace Generators.Methods
5
+ {
6
+ public class TestMethodNameTransformer : IStringTransformer
7
+ {
8
+ public string Transform(string input)
9
+ {
10
+ var methodName = Regex.Replace(input, @"[^\w]+", "_", RegexOptions.Compiled)
11
+ .Underscore()
12
+ .Transform(To.TitleCase);
13
+
14
+ if (char.IsDigit(methodName[0]))
15
+ return "Number_" + methodName;
16
+
17
+ if (!char.IsLetter(methodName[0]))
18
+ return "Test_";
19
+
20
+ return methodName;
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,13 @@
1
+ using System;
2
+
3
+ namespace Generators.Methods
4
+ {
5
+ public class TestMethodOptions
6
+ {
7
+ public string InputProperty { get; set; }
8
+ public bool FormatInput { get; set; } = true;
9
+ public bool FormatExpected { get; set; } = true;
10
+ public Type ExceptionType { get; set; } = typeof(ArgumentException);
11
+ public TestedMethodType TestedMethodType { get; set; } = TestedMethodType.Static;
12
+ }
13
+ }
@@ -1,4 +1,4 @@
1
- namespace Generators
1
+ namespace Generators.Methods
2
2
  {
3
3
  public static class TestMethodRenderer
4
4
  {
@@ -1,6 +1,6 @@
1
1
  using Humanizer;
2
2
 
3
- namespace Generators
3
+ namespace Generators.Methods
4
4
  {
5
5
  public class TestedMethodNameTransformer : IStringTransformer
6
6
  {
@@ -0,0 +1,9 @@
1
+ namespace Generators.Methods
2
+ {
3
+ public enum TestedMethodType
4
+ {
5
+ Static,
6
+ Instance,
7
+ Extension
8
+ }
9
+ }
@@ -1,5 +1,7 @@
1
1
  using Generators.Exercises;
2
2
  using System.IO;
3
+ using Generators.Classes;
4
+ using Generators.Data;
3
5
  using Serilog;
4
6
 
5
7
  namespace Generators
@@ -318,6 +318,13 @@
318
318
  "topics": [
319
319
  ]
320
320
  },
321
+ {
322
+ "slug": "diffie-hellman",
323
+ "difficulty": 4,
324
+ "topics": [
325
+ "math"
326
+ ]
327
+ },
321
328
  {
322
329
  "slug": "sieve",
323
330
  "difficulty": 5,
@@ -0,0 +1,10 @@
1
+ For generating random numbers, Erlang's `:rand.uniform` or `Enum.random` are
2
+ good places to start.
3
+
4
+ `:math.pow |> round` can be used to find the power of a number, and `rem` for
5
+ the modulus.
6
+
7
+ Neither of those works particularly well (or quickly) for very large integers.
8
+ Cryptography generally makes use of numbers larger than 1024 bits. Erlang's
9
+ :crypto module has a useful function for finding the modulus of a power,
10
+ particularly for enormous integers, but you might need :binary to decode it.
@@ -0,0 +1,61 @@
1
+ defmodule DiffieHellman do
2
+ @moduledoc """
3
+ Diffie-Hellman is a method of securely exchanging keys in a public-key
4
+ cryptosystem. Two users, Alice and Bob, want to share a secret between
5
+ themselves, while ensuring nobody else can read it.
6
+
7
+ Step 0: Alice and Bob agree on two prime numbers, P and G. An attacker, Eve,
8
+ can intercept these numbers, but without one of Alice or Bob's private keys,
9
+ we'll see Eve can't do anything useful with them.
10
+
11
+ Step 1: Alice and Bob each generate a private key between 1 and P-1.
12
+ P).
13
+
14
+ Step 2: Using the initial primes P and G, Alice and Bob calculate their
15
+ public keys by raising G to the power of their private key, then calculating
16
+ the modulus of that number by P. ((G**private_key) % P)
17
+
18
+ Step 3: Alice and Bob exchange public keys. Alice and Bob calculate a secret
19
+ shared key by raising the other's public key to the power of their private
20
+ key, then doing a modulus of the result by P. Due to the way modulus math
21
+ works, they should both generate the same shared key.
22
+
23
+ Alice calculates: (bob_public ** alice_private) % P
24
+ Bob calculates: (alice_public ** bob_private) % P
25
+
26
+ As long as their private keys are never lost or transmitted, only they know
27
+ their private keys, so even if Eve has P, G, and both public keys, she can't
28
+ do anything with them.
29
+
30
+ A video example is available at:
31
+ https://www.khanacademy.org/computing/computer-science/cryptography/modern-crypt/v/diffie-hellman-key-exchange-part-2
32
+ """
33
+
34
+ @doc """
35
+ Given a prime integer `prime_p`, return a random integer between 1 and `prime_p` - 1
36
+ """
37
+ @spec generate_private_key(prime_p :: integer) :: integer
38
+ def generate_private_key(prime_p) do
39
+ end
40
+
41
+ @doc """
42
+ Given two prime integers as generators (`prime_p` and `prime_g`), and a private key,
43
+ generate a public key using the mathematical formula:
44
+
45
+ (prime_g ** private_key) % prime_p
46
+ """
47
+ @spec generate_public_key(prime_p :: integer, prime_g :: integer, private_key :: integer) :: integer
48
+ def generate_public_key(prime_p, prime_g, private_key) do
49
+ end
50
+
51
+ @doc """
52
+ Given a prime integer `prime_p`, user B's public key, and user A's private key,
53
+ generate a shared secret using the mathematical formula:
54
+
55
+ (public_key_b ** private_key_a) % prime_p
56
+ """
57
+ @spec generate_shared_secret(prime_p :: integer, public_key_b :: integer, private_key_a :: integer) :: integer
58
+ def generate_shared_secret(prime_p, public_key_b, private_key_a) do
59
+ end
60
+ end
61
+