using System; using NUnit.Framework; namespace Developpez.Dotnet.Tests { [TestFixture] public class FuncExtensionsTests { [Test] public void Test_AsCached_NoParam() { int nCalls = 0; Func func = () => { nCalls++; return 42; }; var asCached = func.AsCached(); // On vérifie que func n'est appelée qu'une fois int result = asCached(); Assert.AreEqual(1, nCalls); result = asCached(); result = asCached(); Assert.AreEqual(1, nCalls); // On vérifie qu'un nouveau cache de la fonction func // appelle func une nouvelle fois et une seule var asCached2 = func.AsCached(); result = asCached2(); Assert.AreEqual(2, nCalls); result = asCached2(); result = asCached2(); Assert.AreEqual(2, nCalls); } [Test] public void Test_AsCached_1Param() { int nCalls = 0; Func func = (x) => { nCalls++; return x * x; }; var asCached = func.AsCached(); // On vérifie que func n'est appelée qu'une fois pour // un argument donné int result = asCached(1); Assert.AreEqual(1, nCalls); result = asCached(1); result = asCached(1); Assert.AreEqual(1, nCalls); // On vérifie que func est appelée une nouvelle fois et // une seule pour une nouvelle valeur de l'argument result = asCached(42); Assert.AreEqual(2, nCalls); result = asCached(42); result = asCached(42); Assert.AreEqual(2, nCalls); // On vérifie qu'un nouveau cache de la fonction func // appelle func une nouvelle fois et une seule pour les // mêmes valeurs d'argument var asCached2 = func.AsCached(); result = asCached2(1); Assert.AreEqual(3, nCalls); result = asCached2(1); result = asCached2(1); Assert.AreEqual(3, nCalls); result = asCached2(42); Assert.AreEqual(4, nCalls); result = asCached2(42); result = asCached2(42); Assert.AreEqual(4, nCalls); } [Test] public void Test_AsCached_2Params() { int nCalls = 0; Func func = (i, d) => { nCalls++; return i + d; }; var asCached = func.AsCached(); // On vérifie que func n'est appelée qu'une fois pour // une liste d'arguments donnée double result = asCached(1, 2.5); Assert.AreEqual(1, nCalls); result = asCached(1, 2.5); result = asCached(1, 2.5); Assert.AreEqual(1, nCalls); // On vérifie que func est appelée une nouvelle fois et // une seule pour une nouvelle liste d'arguments result = asCached(42, 0.1); Assert.AreEqual(2, nCalls); result = asCached(42, 0.1); result = asCached(42, 0.1); Assert.AreEqual(2, nCalls); // On vérifie qu'un nouveau cache de la fonction func // appelle func une nouvelle fois et une seule pour les // mêmes listes d'arguments var asCached2 = func.AsCached(); result = asCached2(1, 2.5); Assert.AreEqual(3, nCalls); result = asCached2(1, 2.5); result = asCached2(1, 2.5); Assert.AreEqual(3, nCalls); result = asCached2(42, 2.5); Assert.AreEqual(4, nCalls); result = asCached2(42, 2.5); result = asCached2(42, 2.5); Assert.AreEqual(4, nCalls); } [Test] public void Test_AsCached_3Params() { int nCalls = 0; Func func = (i, d, d2) => { nCalls++; if (i == null) return 0; return i.Length + d.Length + d2.Length; }; var asCached = func.AsCached(); // On vérifie que func n'est appelée qu'une fois pour // une liste d'arguments donnée double result = asCached("1", "2.5", "2.5"); Assert.AreEqual(1, nCalls); result = asCached("1", "2.5", "2.5"); result = asCached("1", "2.5", "2.5"); Assert.AreEqual(1, nCalls); // On vérifie que func est appelée une nouvelle fois et // une seule pour une nouvelle liste d'arguments result = asCached("42", "2.5", "2.5"); Assert.AreEqual(2, nCalls); result = asCached(null, "2.5", "2.5"); result = asCached("42", "2.5", "2.5"); Assert.AreEqual(3, nCalls); // On vérifie qu'un nouveau cache de la fonction func // appelle func une nouvelle fois et une seule pour les // mêmes listes d'arguments var asCached2 = func.AsCached(); result = asCached2("1", "2.5", "2.5"); Assert.AreEqual(4, nCalls); result = asCached2("1", "2.5", "2.5"); result = asCached2("1", "2.5", "2.5"); Assert.AreEqual(4, nCalls); result = asCached2("42", "2.5", "2.5"); Assert.AreEqual(5, nCalls); result = asCached2("42", "2.5", "2.5"); result = asCached2("42", "2.5", "2.5"); Assert.AreEqual(5, nCalls); } [Test] public void Test_AsCached_4Params() { int nCalls = 0; Func func = (i, d, b, s) => { nCalls++; return b ? i + d * s.Length : i * d + s.Length; }; var asCached = func.AsCached(); // On vérifie que func n'est appelée qu'une fois pour // une liste d'arguments donnée double result = asCached(1, 2.5, true, "hello world"); Assert.AreEqual(1, nCalls); result = asCached(1, 2.5, true, "hello world"); result = asCached(1, 2.5, true, "hello world"); Assert.AreEqual(1, nCalls); // On vérifie que func est appelée une nouvelle fois et // une seule pour une nouvelle liste d'arguments result = asCached(42, 0.1, false, "foo bar"); Assert.AreEqual(2, nCalls); result = asCached(42, 0.1, false, "foo bar"); result = asCached(42, 0.1, false, "foo bar"); Assert.AreEqual(2, nCalls); // On vérifie qu'un nouveau cache de la fonction func // appelle func une nouvelle fois et une seule pour les // mêmes listes d'arguments var asCached2 = func.AsCached(); result = asCached2(1, 2.5, true, "hello world"); Assert.AreEqual(3, nCalls); result = asCached2(1, 2.5, true, "hello world"); result = asCached2(1, 2.5, true, "hello world"); Assert.AreEqual(3, nCalls); result = asCached2(42, 0.1, false, "foo bar"); Assert.AreEqual(4, nCalls); result = asCached2(42, 0.1, false, "foo bar"); result = asCached2(42, 0.1, false, "foo bar"); Assert.AreEqual(4, nCalls); } [Test] public void Test_Curry_Func_2Params() { Func function = (a, b) => a / b; var curried = function.Curry(); Random rnd = new Random(); int x = 1 + rnd.Next(int.MaxValue - 1); int y = 1 + rnd.Next(int.MaxValue - 1); double expected = function(x, y); double actual = curried(x)(y); Assert.AreEqual(expected, actual); } [Test] public void Test_Curry_Action_2Params() { double result = 0; Action action = (a, b) => result = a / b; var curried = action.Curry(); Random rnd = new Random(); int x = 1 + rnd.Next(int.MaxValue - 1); int y = 1 + rnd.Next(int.MaxValue - 1); action(x, y); double expected = result; result = 0; curried(x)(y); double actual = result; Assert.AreEqual(expected, actual); } [Test] public void Test_Curry_Func_3Params() { Func function = (a, b, c) => a + b / c; var curried = function.Curry(); Random rnd = new Random(); int x = 1 + rnd.Next(int.MaxValue - 1); int y = 1 + rnd.Next(int.MaxValue - 1); int z = 1 + rnd.Next(int.MaxValue - 1); double expected = function(x, y, z); double actual = curried(x)(y)(z); Assert.AreEqual(expected, actual); } [Test] public void Test_Curry_Action_3Params() { double result = 0; Action action = (a, b, c) => result = a + b / c; var curried = action.Curry(); Random rnd = new Random(); int x = 1 + rnd.Next(int.MaxValue - 1); int y = 1 + rnd.Next(int.MaxValue - 1); int z = 1 + rnd.Next(int.MaxValue - 1); action(x, y, z); double expected = result; result = 0; curried(x)(y)(z); double actual = result; Assert.AreEqual(expected, actual); } [Test] public void Test_Curry_Func_4Params() { Func function = (a, b, c, d) => a + b / c - d; var curried = function.Curry(); Random rnd = new Random(); int w = 1 + rnd.Next(int.MaxValue - 1); int x = 1 + rnd.Next(int.MaxValue - 1); int y = 1 + rnd.Next(int.MaxValue - 1); int z = 1 + rnd.Next(int.MaxValue - 1); double expected = function(w, x, y, z); double actual = curried(w)(x)(y)(z); Assert.AreEqual(expected, actual); } [Test] public void Test_Curry_Action_4Params() { double result = 0; Action action = (a, b, c, d) => result = a + b / c - d; var curried = action.Curry(); Random rnd = new Random(); int w = 1 + rnd.Next(int.MaxValue - 1); int x = 1 + rnd.Next(int.MaxValue - 1); int y = 1 + rnd.Next(int.MaxValue - 1); int z = 1 + rnd.Next(int.MaxValue - 1); action(w, x, y, z); double expected = result; result = 0; curried(w)(x)(y)(z); double actual = result; Assert.AreEqual(expected, actual); } [Test] public void Test_ApplyFirst_Func_2Params() { Func function = (a, b) => a / b; Random rnd = new Random(); int x = 1 + rnd.Next(int.MaxValue - 1); int y = 1 + rnd.Next(int.MaxValue - 1); var partial = function.ApplyFirst(x); double expected = function(x, y); double actual = partial(y); Assert.AreEqual(expected, actual); } [Test] public void Test_ApplySecond_Func_2Params() { Func function = (a, b) => a / b; Random rnd = new Random(); int x = 1 + rnd.Next(int.MaxValue - 1); int y = 1 + rnd.Next(int.MaxValue - 1); var partial = function.ApplySecond(y); double expected = function(x, y); double actual = partial(x); Assert.AreEqual(expected, actual); } [Test] public void Test_ApplyFirst_Action_2Params() { double result = 0; Action action = (a, b) => result = a / b; Random rnd = new Random(); int x = 1 + rnd.Next(int.MaxValue - 1); int y = 1 + rnd.Next(int.MaxValue - 1); var partial = action.ApplyFirst(x); action(x, y); double expected = result; result = 0; partial(y); double actual = result; Assert.AreEqual(expected, actual); } [Test] public void Test_ApplySecond_Action_2Params() { double result = 0; Action action = (a, b) => result = a / b; Random rnd = new Random(); int x = 1 + rnd.Next(int.MaxValue - 1); int y = 1 + rnd.Next(int.MaxValue - 1); var partial = action.ApplySecond(y); action(x, y); double expected = result; result = 0; partial(x); double actual = result; Assert.AreEqual(expected, actual); } [Test] public void Test_Negate_Predicate() { Predicate predicate = s => s.StartsWith("h"); Predicate negated = predicate.Negate(); string str = "hello"; bool expected = !predicate(str); bool actual = negated(str); Assert.AreEqual(expected, actual); str = "goodbye"; expected = !predicate(str); actual = negated(str); Assert.AreEqual(expected, actual); } [Test] public void Test_Negate_Func() { Func predicate = s => s.StartsWith("h"); Func negated = predicate.Negate(); string str = "hello"; bool expected = !predicate(str); bool actual = negated(str); Assert.AreEqual(expected, actual); str = "goodbye"; expected = !predicate(str); actual = negated(str); Assert.AreEqual(expected, actual); } } }