InteropExplicitTypeTests.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. namespace Jint.Tests.Runtime;
  2. using Jint.Runtime.Interop;
  3. public class InteropExplicitTypeTests
  4. {
  5. public interface I1
  6. {
  7. string Name { get; }
  8. }
  9. public class Super
  10. {
  11. public string Name { get; } = "Super";
  12. }
  13. public class CI1 : Super, I1
  14. {
  15. public new string Name { get; } = "CI1";
  16. string I1.Name { get; } = "CI1 as I1";
  17. }
  18. public class Indexer<T>
  19. {
  20. private readonly T t;
  21. public Indexer(T t)
  22. {
  23. this.t = t;
  24. }
  25. public T this[int index]
  26. {
  27. get { return t; }
  28. }
  29. }
  30. public class InterfaceHolder
  31. {
  32. public InterfaceHolder()
  33. {
  34. var ci1 = new CI1();
  35. this.ci1 = ci1;
  36. this.i1 = ci1;
  37. this.super = ci1;
  38. this.IndexerCI1 = new Indexer<CI1>(ci1);
  39. this.IndexerI1 = new Indexer<I1>(ci1);
  40. this.IndexerSuper = new Indexer<Super>(ci1);
  41. }
  42. public readonly CI1 ci1;
  43. public readonly I1 i1;
  44. public readonly Super super;
  45. public CI1 CI1 { get => ci1; }
  46. public I1 I1 { get => i1; }
  47. public Super Super { get => super; }
  48. public CI1 GetCI1() => ci1;
  49. public I1 GetI1() => i1;
  50. public Super GetSuper() => super;
  51. public Indexer<CI1> IndexerCI1 { get; }
  52. public Indexer<I1> IndexerI1 { get; }
  53. public Indexer<Super> IndexerSuper { get; }
  54. }
  55. private readonly Engine _engine;
  56. private readonly InterfaceHolder holder;
  57. public InteropExplicitTypeTests()
  58. {
  59. holder = new InterfaceHolder();
  60. _engine = new Engine(cfg => cfg.AllowClr(
  61. typeof(CI1).Assembly,
  62. typeof(Console).Assembly,
  63. typeof(File).Assembly))
  64. .SetValue("log", new Action<object>(Console.WriteLine))
  65. .SetValue("assert", new Action<bool>(Assert.True))
  66. .SetValue("equal", new Action<object, object>(Assert.Equal))
  67. .SetValue("holder", holder)
  68. ;
  69. }
  70. [Fact]
  71. public void EqualTest()
  72. {
  73. Assert.Equal(_engine.Evaluate("holder.I1"), _engine.Evaluate("holder.i1"));
  74. Assert.NotEqual(_engine.Evaluate("holder.I1"), _engine.Evaluate("holder.ci1"));
  75. Assert.Equal(_engine.Evaluate("holder.Super"), _engine.Evaluate("holder.super"));
  76. Assert.NotEqual(_engine.Evaluate("holder.Super"), _engine.Evaluate("holder.ci1"));
  77. }
  78. [Fact]
  79. public void ExplicitInterfaceFromField()
  80. {
  81. Assert.Equal(holder.i1.Name, _engine.Evaluate("holder.i1.Name"));
  82. Assert.NotEqual(holder.i1.Name, _engine.Evaluate("holder.ci1.Name"));
  83. }
  84. [Fact]
  85. public void ExplicitInterfaceFromProperty()
  86. {
  87. Assert.Equal(holder.I1.Name, _engine.Evaluate("holder.I1.Name"));
  88. Assert.NotEqual(holder.I1.Name, _engine.Evaluate("holder.CI1.Name"));
  89. }
  90. [Fact]
  91. public void ExplicitInterfaceFromMethod()
  92. {
  93. Assert.Equal(holder.GetI1().Name, _engine.Evaluate("holder.GetI1().Name"));
  94. Assert.NotEqual(holder.GetI1().Name, _engine.Evaluate("holder.GetCI1().Name"));
  95. }
  96. [Fact]
  97. public void ExplicitInterfaceFromIndexer()
  98. {
  99. Assert.Equal(holder.IndexerI1[0].Name, _engine.Evaluate("holder.IndexerI1[0].Name"));
  100. }
  101. [Fact]
  102. public void SuperClassFromField()
  103. {
  104. Assert.Equal(holder.super.Name, _engine.Evaluate("holder.super.Name"));
  105. Assert.NotEqual(holder.super.Name, _engine.Evaluate("holder.ci1.Name"));
  106. }
  107. [Fact]
  108. public void SuperClassFromProperty()
  109. {
  110. Assert.Equal(holder.Super.Name, _engine.Evaluate("holder.Super.Name"));
  111. Assert.NotEqual(holder.Super.Name, _engine.Evaluate("holder.CI1.Name"));
  112. }
  113. [Fact]
  114. public void SuperClassFromMethod()
  115. {
  116. Assert.Equal(holder.GetSuper().Name, _engine.Evaluate("holder.GetSuper().Name"));
  117. Assert.NotEqual(holder.GetSuper().Name, _engine.Evaluate("holder.GetCI1().Name"));
  118. }
  119. [Fact]
  120. public void SuperClassFromIndexer()
  121. {
  122. Assert.Equal(holder.IndexerSuper[0].Name, _engine.Evaluate("holder.IndexerSuper[0].Name"));
  123. }
  124. public struct NullabeStruct : I1
  125. {
  126. public NullabeStruct()
  127. {
  128. }
  129. public string name = "NullabeStruct";
  130. public string Name { get => name; }
  131. string I1.Name { get => "NullabeStruct as I1"; }
  132. }
  133. public class NullableHolder
  134. {
  135. public I1 I1 { get; set; }
  136. public NullabeStruct? NullabeStruct { get; set; }
  137. }
  138. [Fact]
  139. public void TypedObjectWrapperForNullableType()
  140. {
  141. var nullableHolder = new NullableHolder();
  142. _engine.SetValue("nullableHolder", nullableHolder);
  143. _engine.SetValue("nullabeStruct", new NullabeStruct());
  144. Assert.Equal(_engine.Evaluate("nullableHolder.NullabeStruct"), Native.JsValue.Null);
  145. _engine.Evaluate("nullableHolder.NullabeStruct = nullabeStruct");
  146. Assert.Equal(_engine.Evaluate("nullableHolder.NullabeStruct.Name"), nullableHolder.NullabeStruct?.Name);
  147. }
  148. [Fact]
  149. public void ClrHelperUnwrap()
  150. {
  151. Assert.NotEqual(holder.CI1.Name, _engine.Evaluate("holder.I1.Name"));
  152. Assert.Equal(holder.CI1.Name, _engine.Evaluate("clrHelper.unwrap(holder.I1).Name"));
  153. }
  154. [Fact]
  155. public void ClrHelperWrap()
  156. {
  157. _engine.Execute("Jint = importNamespace('Jint');");
  158. Assert.NotEqual(holder.I1.Name, _engine.Evaluate("holder.CI1.Name"));
  159. Assert.Equal(holder.I1.Name, _engine.Evaluate("clrHelper.wrap(holder.CI1, Jint.Tests.Runtime.InteropExplicitTypeTests.I1).Name"));
  160. }
  161. [Fact]
  162. public void ClrHelperTypeOf()
  163. {
  164. Action<Engine> runner = engine =>
  165. {
  166. engine.SetValue("clrobj", new object());
  167. Assert.Equal(engine.Evaluate("System.Object"), engine.Evaluate("clrHelper.typeOf(clrobj)"));
  168. };
  169. runner.Invoke(new Engine(cfg =>
  170. {
  171. cfg.AllowClr();
  172. cfg.Interop.AllowGetType = true;
  173. }));
  174. var ex = Assert.Throws<InvalidOperationException>(() =>
  175. {
  176. runner.Invoke(new Engine(cfg =>
  177. {
  178. cfg.AllowClr();
  179. }));
  180. });
  181. Assert.Equal("Invalid when Engine.Options.Interop.AllowGetType == false", ex.Message);
  182. }
  183. [Fact]
  184. public void ClrHelperTypeOfForNestedType()
  185. {
  186. var engine = new Engine(cfg =>
  187. {
  188. cfg.AllowClr(GetType().Assembly);
  189. cfg.Interop.AllowGetType = true;
  190. });
  191. engine.SetValue("holder", holder);
  192. engine.Execute("Jint = importNamespace('Jint');");
  193. Assert.Equal(engine.Evaluate("Jint.Tests.Runtime.InteropExplicitTypeTests.CI1"), engine.Evaluate("clrHelper.typeOf(holder.CI1)"));
  194. Assert.Equal(engine.Evaluate("Jint.Tests.Runtime.InteropExplicitTypeTests.I1"), engine.Evaluate("clrHelper.typeOf(holder.I1)"));
  195. }
  196. public class TypeHolder
  197. {
  198. public static Type Type => typeof(TypeHolder);
  199. }
  200. [Fact]
  201. public void ClrHelperTypeToObject()
  202. {
  203. Action<Engine> runner = engine =>
  204. {
  205. engine.SetValue("TypeHolder", typeof(TypeHolder));
  206. Assert.True(engine.Evaluate("TypeHolder") is TypeReference);
  207. Assert.True(engine.Evaluate("clrHelper.typeToObject(TypeHolder)") is ObjectWrapper);
  208. };
  209. runner.Invoke(new Engine(cfg =>
  210. {
  211. cfg.AllowClr();
  212. cfg.Interop.AllowGetType = true;
  213. }));
  214. var ex = Assert.Throws<InvalidOperationException>(() =>
  215. {
  216. runner.Invoke(new Engine(cfg =>
  217. {
  218. cfg.AllowClr();
  219. }));
  220. });
  221. Assert.Equal("Invalid when Engine.Options.Interop.AllowGetType == false", ex.Message);
  222. }
  223. [Fact]
  224. public void ClrHelperObjectToType()
  225. {
  226. Action<Engine> runner = engine =>
  227. {
  228. engine.SetValue("TypeHolder", typeof(TypeHolder));
  229. Assert.True(engine.Evaluate("TypeHolder.Type") is ObjectWrapper);
  230. Assert.True(engine.Evaluate("clrHelper.objectToType(TypeHolder.Type)") is TypeReference);
  231. };
  232. runner.Invoke(new Engine(cfg =>
  233. {
  234. cfg.AllowClr();
  235. cfg.Interop.AllowGetType = true;
  236. }));
  237. var ex = Assert.Throws<InvalidOperationException>(() =>
  238. {
  239. runner.Invoke(new Engine(cfg =>
  240. {
  241. cfg.AllowClr();
  242. }));
  243. });
  244. Assert.Equal("Invalid when Engine.Options.Interop.AllowGetType == false", ex.Message);
  245. }
  246. }