trackler 2.0.8.19 → 2.0.8.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/common/exercises/phone-number/canonical-data.json +2 -2
- data/lib/trackler/version.rb +1 -1
- data/tracks/c/config.json +7 -0
- data/tracks/c/exercises/react/makefile +16 -0
- data/tracks/c/exercises/react/src/example.c +185 -0
- data/tracks/c/exercises/react/src/react.h +29 -0
- data/tracks/c/exercises/react/test/test_react.c +324 -0
- data/tracks/c/exercises/react/test/vendor/unity.c +1300 -0
- data/tracks/c/exercises/react/test/vendor/unity.h +274 -0
- data/tracks/c/exercises/react/test/vendor/unity_internals.h +701 -0
- data/tracks/csharp/.travis.yml +2 -9
- data/tracks/csharp/appveyor.yml +3 -3
- data/tracks/csharp/build.cake +13 -4
- data/tracks/csharp/build.ps1 +56 -164
- data/tracks/csharp/build.sh +33 -78
- data/tracks/csharp/circle.yml +2 -4
- data/tracks/csharp/config.json +2 -1
- data/tracks/csharp/exercises/leap/LeapTest.cs +8 -8
- data/tracks/csharp/generators/CanonicalData.cs +19 -0
- data/tracks/csharp/generators/CanonicalDataCase.cs +24 -0
- data/tracks/csharp/generators/CanonicalDataCaseJsonConverter.cs +32 -0
- data/tracks/csharp/generators/CanonicalDataCasesJsonConverter.cs +30 -0
- data/tracks/csharp/generators/CanonicalDataParser.cs +28 -0
- data/tracks/csharp/generators/ExerciseCollection.cs +23 -0
- data/tracks/csharp/generators/Exercises/Exercise.cs +14 -0
- data/tracks/csharp/generators/Exercises/LeapExercise.cs +35 -0
- data/tracks/csharp/generators/Generators.csproj +12 -0
- data/tracks/csharp/generators/Generators.csproj.user +6 -0
- data/tracks/csharp/generators/Generators.sln +22 -0
- data/tracks/csharp/generators/Program.cs +59 -0
- data/tracks/csharp/generators/TestClass.cs +13 -0
- data/tracks/csharp/generators/TestClassRenderer.cs +36 -0
- data/tracks/csharp/generators/TestMethod.cs +9 -0
- data/tracks/csharp/generators/TestMethodNameTransformer.cs +11 -0
- data/tracks/csharp/generators/TestMethodRenderer.cs +18 -0
- data/tracks/csharp/generators/To.cs +7 -0
- data/tracks/csharp/generators/generate.ps1 +2 -0
- data/tracks/csharp/generators/generate.sh +4 -0
- data/tracks/delphi/config.json +8 -0
- data/tracks/delphi/exercises/phone-number/uPhoneNumberExample.pas +6 -6
- data/tracks/delphi/exercises/phone-number/uPhoneNumberTests.pas +28 -17
- data/tracks/delphi/exercises/roman-numerals/RomanNumerals.dpr +60 -0
- data/tracks/delphi/exercises/roman-numerals/uRomanNumeralsExample.pas +49 -0
- data/tracks/delphi/exercises/roman-numerals/uRomanNumeralsTest.pas +216 -0
- data/tracks/elixir/config.json +22 -0
- data/tracks/elixir/exercises/poker/example.exs +136 -0
- data/tracks/elixir/exercises/poker/poker.exs +34 -0
- data/tracks/elixir/exercises/poker/poker_test.exs +217 -0
- data/tracks/elixir/exercises/protein-translation/example.exs +62 -0
- data/tracks/elixir/exercises/protein-translation/protein_translation.exs +34 -0
- data/tracks/elixir/exercises/protein-translation/protein_translation_test.exs +87 -0
- data/tracks/elixir/exercises/say/example.exs +139 -0
- data/tracks/elixir/exercises/say/say.exs +8 -0
- data/tracks/elixir/exercises/say/say_test.exs +85 -0
- data/tracks/go/exercises/robot-name/example.go +2 -0
- data/tracks/go/exercises/robot-name/robot_name_test.go +9 -1
- data/tracks/go/exercises/roman-numerals/roman_numerals_test.go +4 -1
- data/tracks/go/exercises/saddle-points/saddle_points_test.go +6 -6
- data/tracks/php/config.json +7 -0
- data/tracks/php/exercises/grade-school/example.php +35 -0
- data/tracks/php/exercises/grade-school/grade-school_test.php +84 -0
- metadata +43 -2
data/tracks/csharp/config.json
CHANGED
@@ -3,26 +3,26 @@ using Xunit;
|
|
3
3
|
public class LeapTest
|
4
4
|
{
|
5
5
|
[Fact]
|
6
|
-
public void
|
6
|
+
public void Year_not_divisible_by_4_is_common_year()
|
7
7
|
{
|
8
|
-
Assert.
|
8
|
+
Assert.False(Year.IsLeap(2015));
|
9
9
|
}
|
10
10
|
|
11
11
|
[Fact(Skip = "Remove to run test")]
|
12
|
-
public void
|
12
|
+
public void Year_divisible_by_4_not_divisible_by_100_is_leap_year()
|
13
13
|
{
|
14
|
-
Assert.
|
14
|
+
Assert.True(Year.IsLeap(2016));
|
15
15
|
}
|
16
16
|
|
17
17
|
[Fact(Skip = "Remove to run test")]
|
18
|
-
public void
|
18
|
+
public void Year_divisible_by_100_not_divisible_by_400_is_common_year()
|
19
19
|
{
|
20
|
-
Assert.False(Year.IsLeap(
|
20
|
+
Assert.False(Year.IsLeap(2100));
|
21
21
|
}
|
22
22
|
|
23
23
|
[Fact(Skip = "Remove to run test")]
|
24
|
-
public void
|
24
|
+
public void Year_divisible_by_400_is_leap_year()
|
25
25
|
{
|
26
|
-
Assert.True(Year.IsLeap(
|
26
|
+
Assert.True(Year.IsLeap(2000));
|
27
27
|
}
|
28
28
|
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
using System.ComponentModel.DataAnnotations;
|
2
|
+
using Newtonsoft.Json;
|
3
|
+
|
4
|
+
namespace Generators
|
5
|
+
{
|
6
|
+
public class CanonicalData
|
7
|
+
{
|
8
|
+
[Required]
|
9
|
+
public string Exercise { get; set; }
|
10
|
+
|
11
|
+
[Required]
|
12
|
+
public string Version { get; set; }
|
13
|
+
|
14
|
+
public string[] Comments { get; set; }
|
15
|
+
|
16
|
+
[JsonConverter(typeof(CanonicalDataCasesJsonConverter))]
|
17
|
+
public CanonicalDataCase[] Cases { get; set; }
|
18
|
+
}
|
19
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
using Newtonsoft.Json;
|
2
|
+
using System.Collections.Generic;
|
3
|
+
using System.ComponentModel.DataAnnotations;
|
4
|
+
|
5
|
+
namespace Generators
|
6
|
+
{
|
7
|
+
[JsonConverter(typeof(CanonicalDataCaseJsonConverter))]
|
8
|
+
public class CanonicalDataCase
|
9
|
+
{
|
10
|
+
[Required]
|
11
|
+
public string Description { get; set; }
|
12
|
+
|
13
|
+
[Required]
|
14
|
+
public string Property { get; set; }
|
15
|
+
|
16
|
+
public string[] Comments { get; set; }
|
17
|
+
|
18
|
+
public object Input { get; set; }
|
19
|
+
|
20
|
+
public object Expected { get; set; }
|
21
|
+
|
22
|
+
public IDictionary<string, object> Data { get; set; }
|
23
|
+
}
|
24
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
using System;
|
2
|
+
using System.Collections.Generic;
|
3
|
+
using Newtonsoft.Json;
|
4
|
+
using Newtonsoft.Json.Linq;
|
5
|
+
|
6
|
+
namespace Generators
|
7
|
+
{
|
8
|
+
public class CanonicalDataCaseJsonConverter : JsonConverter
|
9
|
+
{
|
10
|
+
public override bool CanConvert(Type objectType)
|
11
|
+
{
|
12
|
+
return typeof(CanonicalDataCase) == objectType;
|
13
|
+
}
|
14
|
+
|
15
|
+
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
16
|
+
{
|
17
|
+
var jToken = JToken.ReadFrom(reader);
|
18
|
+
|
19
|
+
var canonicalDataCase = new CanonicalDataCase();
|
20
|
+
serializer.Populate(new JTokenReader(jToken), canonicalDataCase);
|
21
|
+
|
22
|
+
canonicalDataCase.Data = jToken.ToObject<IDictionary<string, object>>();
|
23
|
+
|
24
|
+
return canonicalDataCase;
|
25
|
+
}
|
26
|
+
|
27
|
+
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
28
|
+
{
|
29
|
+
throw new NotImplementedException();
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
using System;
|
2
|
+
using System.Collections.Generic;
|
3
|
+
using System.Reflection;
|
4
|
+
using Newtonsoft.Json;
|
5
|
+
using Newtonsoft.Json.Linq;
|
6
|
+
using System.Linq;
|
7
|
+
|
8
|
+
namespace Generators
|
9
|
+
{
|
10
|
+
public class CanonicalDataCasesJsonConverter : JsonConverter
|
11
|
+
{
|
12
|
+
public override bool CanConvert(Type objectType)
|
13
|
+
{
|
14
|
+
return typeof(IEnumerable<CanonicalData>).GetTypeInfo().IsAssignableFrom(objectType);
|
15
|
+
}
|
16
|
+
|
17
|
+
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
18
|
+
{
|
19
|
+
var casesToken = JToken.ReadFrom(reader);
|
20
|
+
var caseTokens = casesToken.SelectTokens("$..*[?(@.property)]").ToArray();
|
21
|
+
|
22
|
+
return new JArray(caseTokens).ToObject(objectType);
|
23
|
+
}
|
24
|
+
|
25
|
+
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
26
|
+
{
|
27
|
+
throw new NotImplementedException();
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
using Newtonsoft.Json;
|
2
|
+
using System;
|
3
|
+
using System.ComponentModel.DataAnnotations;
|
4
|
+
using System.Net.Http;
|
5
|
+
|
6
|
+
namespace Generators
|
7
|
+
{
|
8
|
+
public static class CanonicalDataParser
|
9
|
+
{
|
10
|
+
private static readonly HttpClient httpClient = new HttpClient();
|
11
|
+
|
12
|
+
public static CanonicalData Parse(string exercise)
|
13
|
+
{
|
14
|
+
var canonicalDataJson = DownloadCanonicalDataJson(exercise);
|
15
|
+
var canonicalData = JsonConvert.DeserializeObject<CanonicalData>(canonicalDataJson);
|
16
|
+
|
17
|
+
Validator.ValidateObject(canonicalData, new ValidationContext(canonicalData));
|
18
|
+
|
19
|
+
return canonicalData;
|
20
|
+
}
|
21
|
+
|
22
|
+
private static string DownloadCanonicalDataJson(string exercise)
|
23
|
+
=> httpClient.GetStringAsync(GetCanonicalDataUrl(exercise)).GetAwaiter().GetResult();
|
24
|
+
|
25
|
+
private static Uri GetCanonicalDataUrl(string exercise)
|
26
|
+
=> new Uri($"https://raw.githubusercontent.com/exercism/x-common/master/exercises/{exercise}/canonical-data.json");
|
27
|
+
}
|
28
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
using Generators.Exercises;
|
2
|
+
using System;
|
3
|
+
using System.Collections;
|
4
|
+
using System.Collections.Generic;
|
5
|
+
using System.Linq;
|
6
|
+
using System.Reflection;
|
7
|
+
|
8
|
+
namespace Generators
|
9
|
+
{
|
10
|
+
public class ExerciseCollection : IEnumerable<Exercise>
|
11
|
+
{
|
12
|
+
private readonly IEnumerable<Exercise> generators = GetDefinedGenerators();
|
13
|
+
|
14
|
+
public IEnumerator<Exercise> GetEnumerator() => generators.GetEnumerator();
|
15
|
+
|
16
|
+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
17
|
+
|
18
|
+
private static IEnumerable<Exercise> GetDefinedGenerators() =>
|
19
|
+
from type in Assembly.GetEntryAssembly().GetTypes()
|
20
|
+
where typeof(Exercise).IsAssignableFrom(type) && !type.GetTypeInfo().IsAbstract
|
21
|
+
select (Exercise)Activator.CreateInstance(type);
|
22
|
+
}
|
23
|
+
}
|
@@ -0,0 +1,35 @@
|
|
1
|
+
using System;
|
2
|
+
using System.Linq;
|
3
|
+
using Humanizer;
|
4
|
+
|
5
|
+
namespace Generators.Exercises
|
6
|
+
{
|
7
|
+
public class LeapExercise : Exercise
|
8
|
+
{
|
9
|
+
public LeapExercise() : base("leap")
|
10
|
+
{
|
11
|
+
}
|
12
|
+
|
13
|
+
public override TestClass CreateTestClass(CanonicalData canonicalData)
|
14
|
+
{
|
15
|
+
return new TestClass
|
16
|
+
{
|
17
|
+
ClassName = "Leap",
|
18
|
+
TestMethods = canonicalData.Cases.Select(CreateTestMethod).ToArray()
|
19
|
+
};
|
20
|
+
}
|
21
|
+
|
22
|
+
private static TestMethod CreateTestMethod(CanonicalDataCase canonicalDataCase, int index)
|
23
|
+
{
|
24
|
+
var year = Convert.ToInt32(canonicalDataCase.Input);
|
25
|
+
var isTrue = Convert.ToBoolean(canonicalDataCase.Expected);
|
26
|
+
|
27
|
+
return new TestMethod
|
28
|
+
{
|
29
|
+
Index = index,
|
30
|
+
MethodName = canonicalDataCase.Description.Replace(":", " is").Transform(To.TestMethodName),
|
31
|
+
Body = $"Assert.{isTrue}(Year.IsLeap({year}));"
|
32
|
+
};
|
33
|
+
}
|
34
|
+
}
|
35
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
2
|
+
<PropertyGroup>
|
3
|
+
<OutputType>Exe</OutputType>
|
4
|
+
<TargetFramework>netcoreapp1.1</TargetFramework>
|
5
|
+
</PropertyGroup>
|
6
|
+
<ItemGroup>
|
7
|
+
<PackageReference Include="Humanizer" Version="2.1.0" />
|
8
|
+
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
|
9
|
+
<PackageReference Include="serilog" Version="2.4.0" />
|
10
|
+
<PackageReference Include="serilog.sinks.literate" Version="2.1.0" />
|
11
|
+
</ItemGroup>
|
12
|
+
</Project>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
Microsoft Visual Studio Solution File, Format Version 12.00
|
3
|
+
# Visual Studio 15
|
4
|
+
VisualStudioVersion = 15.0.26228.4
|
5
|
+
MinimumVisualStudioVersion = 10.0.40219.1
|
6
|
+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Generators", "Generators.csproj", "{F310316B-5E18-4E7F-A77D-D26AD8D92307}"
|
7
|
+
EndProject
|
8
|
+
Global
|
9
|
+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
10
|
+
Debug|Any CPU = Debug|Any CPU
|
11
|
+
Release|Any CPU = Release|Any CPU
|
12
|
+
EndGlobalSection
|
13
|
+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
14
|
+
{F310316B-5E18-4E7F-A77D-D26AD8D92307}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
15
|
+
{F310316B-5E18-4E7F-A77D-D26AD8D92307}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
16
|
+
{F310316B-5E18-4E7F-A77D-D26AD8D92307}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
17
|
+
{F310316B-5E18-4E7F-A77D-D26AD8D92307}.Release|Any CPU.Build.0 = Release|Any CPU
|
18
|
+
EndGlobalSection
|
19
|
+
GlobalSection(SolutionProperties) = preSolution
|
20
|
+
HideSolutionNode = FALSE
|
21
|
+
EndGlobalSection
|
22
|
+
EndGlobal
|
@@ -0,0 +1,59 @@
|
|
1
|
+
using Generators.Exercises;
|
2
|
+
using System.IO;
|
3
|
+
using Humanizer;
|
4
|
+
using Serilog;
|
5
|
+
|
6
|
+
namespace Generators
|
7
|
+
{
|
8
|
+
public static class Program
|
9
|
+
{
|
10
|
+
public static void Main()
|
11
|
+
{
|
12
|
+
SetupLogger();
|
13
|
+
GenerateAll();
|
14
|
+
}
|
15
|
+
|
16
|
+
private static void SetupLogger()
|
17
|
+
{
|
18
|
+
Log.Logger = new LoggerConfiguration()
|
19
|
+
.WriteTo.LiterateConsole()
|
20
|
+
.CreateLogger();
|
21
|
+
}
|
22
|
+
|
23
|
+
private static void GenerateAll()
|
24
|
+
{
|
25
|
+
Log.Information("Start generating tests...");
|
26
|
+
|
27
|
+
foreach (var exercise in new ExerciseCollection())
|
28
|
+
TestFileGenerator.Generate(exercise);
|
29
|
+
|
30
|
+
Log.Information("Finished generating tests for all supported exercises.");
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
public static class TestFileGenerator
|
35
|
+
{
|
36
|
+
public static void Generate(Exercise exercise)
|
37
|
+
{
|
38
|
+
var testClassContents = GenerateTestClassContents(exercise);
|
39
|
+
var testClassFilePath = TestFilePath(exercise);
|
40
|
+
|
41
|
+
SaveTestClassContentsToFile(testClassFilePath, testClassContents);
|
42
|
+
Log.Information("Generated tests for {Exercise} exercise in {TestFile}.", exercise.Name, testClassFilePath);
|
43
|
+
}
|
44
|
+
|
45
|
+
private static string GenerateTestClassContents(Exercise exercise)
|
46
|
+
{
|
47
|
+
var canonicalData = CanonicalDataParser.Parse(exercise.Name);
|
48
|
+
var testClass = exercise.CreateTestClass(canonicalData);
|
49
|
+
return TestClassRenderer.Render(testClass);
|
50
|
+
}
|
51
|
+
|
52
|
+
private static void SaveTestClassContentsToFile(string testClassFilePath, string testClassContents) =>
|
53
|
+
File.WriteAllText(testClassFilePath, testClassContents);
|
54
|
+
|
55
|
+
private static string TestFilePath(Exercise exercise) => Path.Combine("..", "exercises", exercise.Name, TestFileName(exercise));
|
56
|
+
|
57
|
+
private static string TestFileName(Exercise exercise) => $"{exercise.Name.Transform(Humanizer.To.TitleCase)}Test.cs";
|
58
|
+
}
|
59
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
using System.Collections.Generic;
|
2
|
+
|
3
|
+
namespace Generators
|
4
|
+
{
|
5
|
+
public class TestClass
|
6
|
+
{
|
7
|
+
public ISet<string> UsingNamespaces { get; set; } = new HashSet<string> { "Xunit" };
|
8
|
+
public string ClassName { get; set; }
|
9
|
+
public string BeforeTestMethods { get; set; }
|
10
|
+
public TestMethod[] TestMethods { get; set; }
|
11
|
+
public string AfterTestMethods { get; set; }
|
12
|
+
}
|
13
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
using System.Collections.Generic;
|
2
|
+
using System.Linq;
|
3
|
+
|
4
|
+
namespace Generators
|
5
|
+
{
|
6
|
+
public static class TestClassRenderer
|
7
|
+
{
|
8
|
+
private const string TestClassTemplate =
|
9
|
+
@"{UsingNamespaces}
|
10
|
+
|
11
|
+
public class {ClassName}Test
|
12
|
+
{
|
13
|
+
{Body}
|
14
|
+
}";
|
15
|
+
|
16
|
+
public static string Render(TestClass testClass) =>
|
17
|
+
TestClassTemplate
|
18
|
+
.Replace("{UsingNamespaces}", RenderUsingNamespaces(testClass))
|
19
|
+
.Replace("{ClassName}", testClass.ClassName)
|
20
|
+
.Replace("{Body}", RenderBody(testClass));
|
21
|
+
|
22
|
+
private static string RenderUsingNamespaces(TestClass testClass) =>
|
23
|
+
string.Join("\n", testClass.UsingNamespaces.Select(usingNamespace => $"using {usingNamespace};"));
|
24
|
+
|
25
|
+
private static string RenderBody(TestClass testClass) =>
|
26
|
+
string.Join("\n\n", GetBodyParts(testClass));
|
27
|
+
|
28
|
+
private static IEnumerable<string> GetBodyParts(TestClass testClass) =>
|
29
|
+
from bodyPart in new [] { testClass.BeforeTestMethods, RenderTestMethods(testClass), testClass.AfterTestMethods }
|
30
|
+
where !string.IsNullOrWhiteSpace(bodyPart)
|
31
|
+
select bodyPart;
|
32
|
+
|
33
|
+
private static string RenderTestMethods(TestClass testClass) =>
|
34
|
+
string.Join("\n\n", testClass.TestMethods.Select(TestMethodRenderer.Render));
|
35
|
+
}
|
36
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
using System.Text.RegularExpressions;
|
2
|
+
using Humanizer;
|
3
|
+
|
4
|
+
namespace Generators
|
5
|
+
{
|
6
|
+
public class TestMethodNameTransformer : IStringTransformer
|
7
|
+
{
|
8
|
+
public string Transform(string input)
|
9
|
+
=> Regex.Replace(input, @"[^\w]+", "_", RegexOptions.Compiled).Underscore().Transform(Humanizer.To.TitleCase);
|
10
|
+
}
|
11
|
+
}
|