trackler 2.0.8.19 → 2.0.8.20
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|