GenericMethodTests.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. namespace Jint.Tests.Runtime;
  2. public class GenericMethodTests
  3. {
  4. [Fact]
  5. public void TestGeneric()
  6. {
  7. var engine = new Engine();
  8. engine.SetValue("TestGenericBaseClass", typeof(TestGenericBaseClass<>));
  9. engine.SetValue("TestGenericClass", typeof(TestGenericClass));
  10. engine.Execute(@"
  11. var testGeneric = new TestGenericClass();
  12. testGeneric.Bar('testing testing 1 2 3');
  13. testGeneric.Foo('hello world');
  14. testGeneric.Add('blah');
  15. ");
  16. Assert.Equal(true, TestGenericClass.BarInvoked);
  17. Assert.Equal(true, TestGenericClass.FooInvoked);
  18. }
  19. [Fact]
  20. public void TestGeneric2()
  21. {
  22. var engine = new Engine();
  23. var testGenericObj = new TestGenericClass();
  24. engine.SetValue("testGenericObj", testGenericObj);
  25. engine.Execute(@"
  26. testGenericObj.Bar('testing testing 1 2 3');
  27. testGenericObj.Foo('hello world');
  28. testGenericObj.Add('blah');
  29. ");
  30. Assert.Equal(1, testGenericObj.Count);
  31. }
  32. [Fact]
  33. public void TestFancyGenericPass()
  34. {
  35. var engine = new Engine();
  36. var testGenericObj = new TestGenericClass();
  37. engine.SetValue("testGenericObj", testGenericObj);
  38. engine.Execute(@"
  39. testGenericObj.Fancy('test', 42, 'foo');
  40. ");
  41. Assert.Equal(true, testGenericObj.FancyInvoked);
  42. }
  43. [Fact]
  44. public void TestFancyGenericFail()
  45. {
  46. var engine = new Engine();
  47. var testGenericObj = new TestGenericClass();
  48. engine.SetValue("testGenericObj", testGenericObj);
  49. var argException = Assert.Throws<Jint.Runtime.JavaScriptException>(() =>
  50. {
  51. engine.Execute(@"
  52. testGenericObj.Fancy('test', 'foo', 42);
  53. ");
  54. });
  55. Assert.Equal("No public methods with the specified arguments were found.", argException.Message);
  56. }
  57. // TPC: TODO: tldr; typescript transpiled to javascript does not include the types in the constructors - JINT should allow you to use generics without specifying type
  58. // The following doesn't work because JINT currently requires generic classes to be instantiated in a way that doesn't comply with typescript transpile of javascript
  59. // i.e. we shouldn't have to specify the type of the generic class when we instantiate it. Since typescript takes the following:
  60. // const someGeneric = new Foo.Bar.MeGeneric<string>()
  61. // and it becomes the following javascript (thru transpile):
  62. // const someGeneric = new Foo.Bar.MeGeneric();
  63. // we _may_ be able to address this by simply instantiating generic types using System.Object for the generic arguments
  64. // This test currently generates the following error:
  65. // No public methods with the specified arguments were found.
  66. [Fact(Skip = "not supported yet")]
  67. public void TestGenericClassDeriveFromGenericInterface()
  68. {
  69. var engine = new Engine(cfg => cfg.AllowClr(typeof(OpenGenericTest<>).Assembly));
  70. engine.SetValue("ClosedGenericTest", typeof(ClosedGenericTest));
  71. engine.SetValue("OpenGenericTest", typeof(OpenGenericTest<>));
  72. engine.SetValue("log", new System.Action<object>(System.Console.WriteLine));
  73. engine.Execute(@"
  74. const closedGenericTest = new ClosedGenericTest();
  75. closedGenericTest.Foo(42);
  76. const temp = new OpenGenericTest(System.String);
  77. ");
  78. }
  79. [Fact]
  80. public void TestGenericMethodUsingCovarianceOrContraviance()
  81. {
  82. var engine = new Engine(cfg => cfg.AllowClr(typeof(PlayerChoiceManager).Assembly));
  83. engine.SetValue("PlayerChoiceManager", typeof(PlayerChoiceManager));
  84. engine.SetValue("TestSelectorWithoutProps", typeof(TestSelectorWithoutProps));
  85. engine.SetValue("TestGenericClass", typeof(TestGenericClass));
  86. // TPC: the following is the C# equivalent
  87. /*
  88. PlayerChoiceManager playerChoiceManager = new PlayerChoiceManager();
  89. var testSelectorWithoutProps = new TestSelectorWithoutProps();
  90. var result = playerChoiceManager.Store.Select(testSelectorWithoutProps);
  91. */
  92. engine.Execute(@"
  93. const playerChoiceManager = new PlayerChoiceManager();
  94. const testSelectorWithoutProps = new TestSelectorWithoutProps();
  95. const result = playerChoiceManager.Store.Select(testSelectorWithoutProps);
  96. ");
  97. Assert.Equal(true, ReduxStore<PlayerChoiceState>.SelectInvoked);
  98. }
  99. public interface IGenericTest<T>
  100. {
  101. void Foo<U>(U u);
  102. }
  103. public class OpenGenericTest<T> : IGenericTest<T>
  104. {
  105. public void Foo<U>(U u)
  106. {
  107. Console.WriteLine("OpenGenericTest: u: " + u);
  108. }
  109. }
  110. public class ClosedGenericTest : IGenericTest<string>
  111. {
  112. public void Foo<U>(U u)
  113. {
  114. Console.WriteLine("ClosedGenericTest: u: " + u);
  115. }
  116. }
  117. public class TestGenericBaseClass<T>
  118. {
  119. private readonly System.Collections.Generic.List<T> _list = new System.Collections.Generic.List<T>();
  120. public int Count
  121. {
  122. get { return _list.Count; }
  123. }
  124. public void Add(T t)
  125. {
  126. _list.Add(t);
  127. }
  128. }
  129. public class TestGenericClass : TestGenericBaseClass<string>
  130. {
  131. public static bool BarInvoked { get; private set; }
  132. public static bool FooInvoked { get; private set; }
  133. public bool FancyInvoked { get; private set; }
  134. public TestGenericClass()
  135. {
  136. BarInvoked = false;
  137. FooInvoked = false;
  138. FancyInvoked = false;
  139. }
  140. public void Bar(string text)
  141. {
  142. Console.WriteLine("TestGenericClass: Bar: text: " + text);
  143. BarInvoked = true;
  144. }
  145. public void Foo<T>(T t)
  146. {
  147. Console.WriteLine("TestGenericClass: Foo: t: " + t);
  148. FooInvoked = true;
  149. }
  150. public void Fancy<T, U>(T t1, U u, T t2)
  151. {
  152. Console.WriteLine("TestGenericClass: FancyInvoked: t1: " + t1 + "u: " + u + " t2: " + t2);
  153. FancyInvoked = true;
  154. }
  155. }
  156. public interface ISelector<in TInput, out TOutput>
  157. {
  158. }
  159. public interface ISelectorWithoutProps<in TInput, out TOutput> : ISelector<TInput, TOutput>
  160. {
  161. IObservable<TOutput> Apply(TInput input);
  162. }
  163. public sealed partial class ReduxStore<TState> where TState : class, new()
  164. {
  165. public static bool SelectInvoked
  166. {
  167. get;
  168. private set;
  169. }
  170. public ReduxStore()
  171. {
  172. SelectInvoked = false;
  173. }
  174. public IObservable<TResult> Select<TResult>(ISelectorWithoutProps<TState, TResult> selector, string optionsStr = null)
  175. {
  176. SelectInvoked = true;
  177. return selector.Apply(null);
  178. }
  179. }
  180. public class ManagerWithStore<Klass, TState> where Klass : ManagerWithStore<Klass, TState>, new() where TState : class, new()
  181. {
  182. public ReduxStore<TState> Store { get; private set; } = null;
  183. public ManagerWithStore()
  184. {
  185. Store = new ReduxStore<TState>();
  186. }
  187. }
  188. public class PlayerChoiceState
  189. {
  190. }
  191. public class TestSelectorWithoutProps : ISelectorWithoutProps<PlayerChoiceState, string>
  192. {
  193. public IObservable<string> Apply(PlayerChoiceState input)
  194. {
  195. return null;
  196. }
  197. }
  198. public class PlayerChoiceManager : ManagerWithStore<PlayerChoiceManager, PlayerChoiceState>
  199. {
  200. }
  201. }