PageRenderTime 63ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/test/System.Json.Test.Integration/Common/InstanceCreator.cs

https://bitbucket.org/mdavid/aspnetwebstack
C# | 1243 lines | 870 code | 123 blank | 250 comment | 126 complexity | 793b27bd9e6d953c63918b7db20f44f6 MD5 | raw file
  1. using System.Collections.Generic;
  2. using System.Reflection;
  3. using System.Runtime.Serialization;
  4. using System.Text;
  5. using System.Text.RegularExpressions;
  6. namespace System.Json
  7. {
  8. /// <summary>
  9. /// Settings used by the <see cref="InstanceCreator"/> class.
  10. /// </summary>
  11. public static class CreatorSettings
  12. {
  13. static CreatorSettings()
  14. {
  15. MaxArrayLength = 10;
  16. MaxListLength = 10;
  17. MaxStringLength = 100;
  18. CreateOnlyAsciiChars = false;
  19. DontCreateSurrogateChars = false;
  20. CreateDateTimeWithSubMilliseconds = true;
  21. NullValueProbability = 0.01;
  22. AvoidStackOverflowDueToTypeCycles = false;
  23. CreatorSurrogate = null;
  24. }
  25. /// <summary>
  26. /// Gets or sets the maximum length of arrays created by the <see cref="InstanceCreator"/>.
  27. /// </summary>
  28. public static int MaxArrayLength { get; set; }
  29. /// <summary>
  30. /// Gets or sets the maximum length of lists created by the <see cref="InstanceCreator"/>.
  31. /// </summary>
  32. public static int MaxListLength { get; set; }
  33. /// <summary>
  34. /// Gets or sets the maximum length of strings created by the <see cref="InstanceCreator"/>.
  35. /// </summary>
  36. public static int MaxStringLength { get; set; }
  37. /// <summary>
  38. /// Gets or sets a flag indicating whether only ascii chars should be used when creating strings.
  39. /// </summary>
  40. public static bool CreateOnlyAsciiChars { get; set; }
  41. /// <summary>
  42. /// Gets or sets a flag indicating whether chars in the surrogate range can be returned by the
  43. /// <see cref="InstanceCreator"/> when creating char instances.
  44. /// </summary>
  45. public static bool DontCreateSurrogateChars { get; set; }
  46. /// <summary>
  47. /// Gets or sets a flag indicating whether <see cref="DateTime"/> values created by the
  48. /// <see cref="InstanceCreator"/> can have submillisecond precision.
  49. /// </summary>
  50. public static bool CreateDateTimeWithSubMilliseconds { get; set; }
  51. /// <summary>
  52. /// Gets or sets a value (0-1) indicating the probability of the <see cref="InstanceCreator"/>
  53. /// returning a <code>null</code> value when creating instances of class types.
  54. /// </summary>
  55. public static double NullValueProbability { get; set; }
  56. /// <summary>
  57. /// Gets or sets a flag indicating whether the protection against stack overflow
  58. /// for cyclic types is enabled. If this flag is set, whenever a type which has already
  59. /// been created up in the stack is created again, the <see cref="InstanceCreator"/>
  60. /// will return the default value for that type.
  61. /// </summary>
  62. public static bool AvoidStackOverflowDueToTypeCycles { get; set; }
  63. /// <summary>
  64. /// Gets or sets the instance of an <see cref="InstanceCreatorSurrogate"/> which can intercept
  65. /// requests to create instances on the <see cref="InstanceCreator"/>.
  66. /// </summary>
  67. public static InstanceCreatorSurrogate CreatorSurrogate { get; set; }
  68. }
  69. /// <summary>
  70. /// Utility class used to create test instances of primitive types.
  71. /// </summary>
  72. public static class PrimitiveCreator
  73. {
  74. static readonly Regex RelativeIPv6UriRegex = new Regex(@"^\/\/(.+\@)?\[\:\:\d\]");
  75. static Dictionary<Type, MethodInfo> creators;
  76. static PrimitiveCreator()
  77. {
  78. Type primitiveCreatorType = typeof(PrimitiveCreator);
  79. creators = new Dictionary<Type, MethodInfo>();
  80. creators.Add(typeof(bool), primitiveCreatorType.GetMethod("CreateInstanceOfBoolean", BindingFlags.Public | BindingFlags.Static));
  81. creators.Add(typeof(byte), primitiveCreatorType.GetMethod("CreateInstanceOfByte", BindingFlags.Public | BindingFlags.Static));
  82. creators.Add(typeof(char), primitiveCreatorType.GetMethod("CreateInstanceOfChar", BindingFlags.Public | BindingFlags.Static));
  83. creators.Add(typeof(DateTime), primitiveCreatorType.GetMethod("CreateInstanceOfDateTime", BindingFlags.Public | BindingFlags.Static));
  84. creators.Add(typeof(DateTimeOffset), primitiveCreatorType.GetMethod("CreateInstanceOfDateTimeOffset", BindingFlags.Public | BindingFlags.Static));
  85. creators.Add(typeof(decimal), primitiveCreatorType.GetMethod("CreateInstanceOfDecimal", BindingFlags.Public | BindingFlags.Static));
  86. creators.Add(typeof(double), primitiveCreatorType.GetMethod("CreateInstanceOfDouble", BindingFlags.Public | BindingFlags.Static));
  87. creators.Add(typeof(Guid), primitiveCreatorType.GetMethod("CreateInstanceOfGuid", BindingFlags.Public | BindingFlags.Static));
  88. creators.Add(typeof(short), primitiveCreatorType.GetMethod("CreateInstanceOfInt16", BindingFlags.Public | BindingFlags.Static));
  89. creators.Add(typeof(int), primitiveCreatorType.GetMethod("CreateInstanceOfInt32", BindingFlags.Public | BindingFlags.Static));
  90. creators.Add(typeof(long), primitiveCreatorType.GetMethod("CreateInstanceOfInt64", BindingFlags.Public | BindingFlags.Static));
  91. creators.Add(typeof(object), primitiveCreatorType.GetMethod("CreateInstanceOfObject", BindingFlags.Public | BindingFlags.Static));
  92. creators.Add(typeof(sbyte), primitiveCreatorType.GetMethod("CreateInstanceOfSByte", BindingFlags.Public | BindingFlags.Static));
  93. creators.Add(typeof(float), primitiveCreatorType.GetMethod("CreateInstanceOfSingle", BindingFlags.Public | BindingFlags.Static));
  94. creators.Add(typeof(string), primitiveCreatorType.GetMethod("CreateInstanceOfString", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(Random) }, null));
  95. creators.Add(typeof(ushort), primitiveCreatorType.GetMethod("CreateInstanceOfUInt16", BindingFlags.Public | BindingFlags.Static));
  96. creators.Add(typeof(uint), primitiveCreatorType.GetMethod("CreateInstanceOfUInt32", BindingFlags.Public | BindingFlags.Static));
  97. creators.Add(typeof(ulong), primitiveCreatorType.GetMethod("CreateInstanceOfUInt64", BindingFlags.Public | BindingFlags.Static));
  98. creators.Add(typeof(Uri), primitiveCreatorType.GetMethod("CreateInstanceOfUri", BindingFlags.Public | BindingFlags.Static));
  99. }
  100. /// <summary>
  101. /// Creates an instance of the <see cref="Boolean"/> type.
  102. /// </summary>
  103. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  104. /// <returns>An instance of the <see cref="Boolean"/> type.</returns>
  105. public static bool CreateInstanceOfBoolean(Random rndGen)
  106. {
  107. return rndGen.Next(2) == 0;
  108. }
  109. /// <summary>
  110. /// Creates an instance of the <see cref="Byte"/> type.
  111. /// </summary>
  112. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  113. /// <returns>An instance of the <see cref="Byte"/> type.</returns>
  114. public static byte CreateInstanceOfByte(Random rndGen)
  115. {
  116. byte[] rndValue = new byte[1];
  117. rndGen.NextBytes(rndValue);
  118. return rndValue[0];
  119. }
  120. /// <summary>
  121. /// Creates an instance of the <see cref="Char"/> type.
  122. /// </summary>
  123. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  124. /// <returns>An instance of the <see cref="Char"/> type.</returns>
  125. public static char CreateInstanceOfChar(Random rndGen)
  126. {
  127. if (CreatorSettings.CreateOnlyAsciiChars)
  128. {
  129. return (char)rndGen.Next(0x20, 0x7F);
  130. }
  131. else if (CreatorSettings.DontCreateSurrogateChars)
  132. {
  133. char c;
  134. do
  135. {
  136. c = (char)rndGen.Next((int)Char.MinValue, (int)Char.MaxValue);
  137. }
  138. while (Char.IsSurrogate(c));
  139. return c;
  140. }
  141. else
  142. {
  143. return (char)rndGen.Next((int)Char.MinValue, (int)Char.MaxValue + 1);
  144. }
  145. }
  146. /// <summary>
  147. /// Creates an instance of the <see cref="DateTime"/> type.
  148. /// </summary>
  149. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  150. /// <returns>An instance of the <see cref="DateTime"/> type.</returns>
  151. public static System.DateTime CreateInstanceOfDateTime(Random rndGen)
  152. {
  153. long temp = CreateInstanceOfInt64(rndGen);
  154. temp = Math.Abs(temp);
  155. DateTime result;
  156. try
  157. {
  158. result = new DateTime(temp % (DateTime.MaxValue.Ticks + 1));
  159. }
  160. catch (ArgumentOutOfRangeException)
  161. {
  162. result = DateTime.Now;
  163. }
  164. int kind = rndGen.Next(3);
  165. switch (kind)
  166. {
  167. case 0:
  168. result = DateTime.SpecifyKind(result, DateTimeKind.Local);
  169. break;
  170. case 1:
  171. result = DateTime.SpecifyKind(result, DateTimeKind.Unspecified);
  172. break;
  173. default:
  174. result = DateTime.SpecifyKind(result, DateTimeKind.Utc);
  175. break;
  176. }
  177. if (!CreatorSettings.CreateDateTimeWithSubMilliseconds)
  178. {
  179. result = new DateTime(
  180. result.Year,
  181. result.Month,
  182. result.Day,
  183. result.Hour,
  184. result.Minute,
  185. result.Second,
  186. result.Millisecond,
  187. result.Kind);
  188. }
  189. return result;
  190. }
  191. /// <summary>
  192. /// Creates an instance of the <see cref="DateTimeOffset"/> type.
  193. /// </summary>
  194. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  195. /// <returns>An instance of the <see cref="DateTimeOffset"/> type.</returns>
  196. public static System.DateTimeOffset CreateInstanceOfDateTimeOffset(Random rndGen)
  197. {
  198. DateTime temp = CreateInstanceOfDateTime(rndGen);
  199. temp = DateTime.SpecifyKind(temp, DateTimeKind.Unspecified);
  200. int offsetMinutes = rndGen.Next(-14 * 60, 14 * 60);
  201. DateTimeOffset result = new DateTimeOffset(temp, TimeSpan.FromMinutes(offsetMinutes));
  202. return result;
  203. }
  204. /// <summary>
  205. /// Creates an instance of the <see cref="Decimal"/> type.
  206. /// </summary>
  207. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  208. /// <returns>An instance of the <see cref="Decimal"/> type.</returns>
  209. public static decimal CreateInstanceOfDecimal(Random rndGen)
  210. {
  211. int low = CreateInstanceOfInt32(rndGen);
  212. int mid = CreateInstanceOfInt32(rndGen);
  213. int high = CreateInstanceOfInt32(rndGen);
  214. bool isNegative = rndGen.Next(2) == 0;
  215. const int MaxDecimalScale = 28;
  216. byte scale = (byte)rndGen.Next(0, MaxDecimalScale + 1);
  217. return new decimal(low, mid, high, isNegative, scale);
  218. }
  219. /// <summary>
  220. /// Creates an instance of the <see cref="Double"/> type.
  221. /// </summary>
  222. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  223. /// <returns>An instance of the <see cref="Double"/> type.</returns>
  224. public static double CreateInstanceOfDouble(Random rndGen)
  225. {
  226. bool negative = rndGen.Next(2) == 0;
  227. int temp = rndGen.Next(40);
  228. double result;
  229. switch (temp)
  230. {
  231. case 0: return Double.NaN;
  232. case 1: return Double.PositiveInfinity;
  233. case 2: return Double.NegativeInfinity;
  234. case 3: return Double.MinValue;
  235. case 4: return Double.MaxValue;
  236. case 5: return Double.Epsilon;
  237. default:
  238. result = (double)(rndGen.NextDouble() * 100000);
  239. if (negative)
  240. {
  241. result = -result;
  242. }
  243. return result;
  244. }
  245. }
  246. /// <summary>
  247. /// Creates an instance of the <see cref="Guid"/> type.
  248. /// </summary>
  249. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  250. /// <returns>An instance of the <see cref="Guid"/> type.</returns>
  251. public static System.Guid CreateInstanceOfGuid(Random rndGen)
  252. {
  253. byte[] temp = new byte[16];
  254. rndGen.NextBytes(temp);
  255. return new Guid(temp);
  256. }
  257. /// <summary>
  258. /// Creates an instance of the <see cref="Int16"/> type.
  259. /// </summary>
  260. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  261. /// <returns>An instance of the <see cref="Int16"/> type.</returns>
  262. public static short CreateInstanceOfInt16(Random rndGen)
  263. {
  264. byte[] rndValue = new byte[2];
  265. rndGen.NextBytes(rndValue);
  266. short result = 0;
  267. for (int i = 0; i < rndValue.Length; i++)
  268. {
  269. result = (short)(result << 8);
  270. result = (short)(result | (short)rndValue[i]);
  271. }
  272. return result;
  273. }
  274. /// <summary>
  275. /// Creates an instance of the <see cref="Int32"/> type.
  276. /// </summary>
  277. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  278. /// <returns>An instance of the <see cref="Int32"/> type.</returns>
  279. public static int CreateInstanceOfInt32(Random rndGen)
  280. {
  281. byte[] rndValue = new byte[4];
  282. rndGen.NextBytes(rndValue);
  283. int result = 0;
  284. for (int i = 0; i < rndValue.Length; i++)
  285. {
  286. result = (int)(result << 8);
  287. result = (int)(result | (int)rndValue[i]);
  288. }
  289. return result;
  290. }
  291. /// <summary>
  292. /// Creates an instance of the <see cref="Int64"/> type.
  293. /// </summary>
  294. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  295. /// <returns>An instance of the <see cref="Int64"/> type.</returns>
  296. public static long CreateInstanceOfInt64(Random rndGen)
  297. {
  298. byte[] rndValue = new byte[8];
  299. rndGen.NextBytes(rndValue);
  300. long result = 0;
  301. for (int i = 0; i < rndValue.Length; i++)
  302. {
  303. result = (long)(result << 8);
  304. result = (long)(result | (long)rndValue[i]);
  305. }
  306. return result;
  307. }
  308. /// <summary>
  309. /// Creates an instance of the <see cref="Object"/> type.
  310. /// </summary>
  311. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  312. /// <returns>An instance of the <see cref="Object"/> type.</returns>
  313. public static object CreateInstanceOfObject(Random rndGen)
  314. {
  315. return (rndGen.Next(5) == 0) ? null : new object();
  316. }
  317. /// <summary>
  318. /// Creates an instance of the <see cref="SByte"/> type.
  319. /// </summary>
  320. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  321. /// <returns>An instance of the <see cref="SByte"/> type.</returns>
  322. [CLSCompliant(false)]
  323. public static sbyte CreateInstanceOfSByte(Random rndGen)
  324. {
  325. byte[] rndValue = new byte[1];
  326. rndGen.NextBytes(rndValue);
  327. sbyte result = (sbyte)rndValue[0];
  328. return result;
  329. }
  330. /// <summary>
  331. /// Creates an instance of the <see cref="Single"/> type.
  332. /// </summary>
  333. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  334. /// <returns>An instance of the <see cref="Single"/> type.</returns>
  335. public static float CreateInstanceOfSingle(Random rndGen)
  336. {
  337. bool negative = rndGen.Next(2) == 0;
  338. int temp = rndGen.Next(40);
  339. float result;
  340. switch (temp)
  341. {
  342. case 0: return Single.NaN;
  343. case 1: return Single.PositiveInfinity;
  344. case 2: return Single.NegativeInfinity;
  345. case 3: return Single.MinValue;
  346. case 4: return Single.MaxValue;
  347. case 5: return Single.Epsilon;
  348. default:
  349. result = (float)(rndGen.NextDouble() * 100000);
  350. if (negative)
  351. {
  352. result = -result;
  353. }
  354. return result;
  355. }
  356. }
  357. /// <summary>
  358. /// Creates an instance of the <see cref="String"/> type.
  359. /// </summary>
  360. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  361. /// <param name="size">The size of the string to be creted.</param>
  362. /// <param name="charsToUse">The characters to use when creating the string.</param>
  363. /// <returns>An instance of the <see cref="String"/> type.</returns>
  364. public static string CreateRandomString(Random rndGen, int size, string charsToUse)
  365. {
  366. int maxSize = CreatorSettings.MaxStringLength;
  367. // invalid per the XML spec (http://www.w3.org/TR/REC-xml/#charsets), cannot be sent as XML
  368. string invalidXmlChars = "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u000B\u000C\u000E\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A\u001B\u001C\u001D\u001E\u001F\uFFFE\uFFFF";
  369. const int LowSurrogateMin = 0xDC00;
  370. const int LowSurrogateMax = 0xDFFF;
  371. const int HighSurrogateMin = 0xD800;
  372. const int HighSurrogateMax = 0xDBFF;
  373. if (size < 0)
  374. {
  375. double rndNumber = rndGen.NextDouble();
  376. if (rndNumber < CreatorSettings.NullValueProbability)
  377. {
  378. return null; // 1% chance of null value
  379. }
  380. size = (int)Math.Pow(maxSize, rndNumber); // this will create more small strings than large ones
  381. size--;
  382. }
  383. StringBuilder sb = new StringBuilder();
  384. for (int i = 0; i < size; i++)
  385. {
  386. char c;
  387. if (charsToUse != null)
  388. {
  389. c = charsToUse[rndGen.Next(charsToUse.Length)];
  390. sb.Append(c);
  391. }
  392. else
  393. {
  394. if (CreatorSettings.CreateOnlyAsciiChars || rndGen.Next(2) == 0)
  395. {
  396. c = (char)rndGen.Next(0x20, 0x7F); // low-ascii chars
  397. sb.Append(c);
  398. }
  399. else
  400. {
  401. do
  402. {
  403. c = (char)rndGen.Next((int)Char.MinValue, (int)Char.MaxValue + 1);
  404. }
  405. while ((LowSurrogateMin <= c && c <= LowSurrogateMax) || (invalidXmlChars.IndexOf(c) >= 0));
  406. sb.Append(c);
  407. if (HighSurrogateMin <= c && c <= HighSurrogateMax)
  408. {
  409. // need to add a low surrogate
  410. c = (char)rndGen.Next(LowSurrogateMin, LowSurrogateMax + 1);
  411. sb.Append(c);
  412. }
  413. }
  414. }
  415. }
  416. return sb.ToString();
  417. }
  418. /// <summary>
  419. /// Creates an instance of the <see cref="String"/> type.
  420. /// </summary>
  421. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  422. /// <returns>An instance of the <see cref="String"/> type.</returns>
  423. public static string CreateInstanceOfString(Random rndGen)
  424. {
  425. return CreateInstanceOfString(rndGen, true);
  426. }
  427. /// <summary>
  428. /// Creates an instance of the <see cref="String"/> type.
  429. /// </summary>
  430. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  431. /// <param name="allowNull">A flag indicating whether null values can be returned.</param>
  432. /// <returns>An instance of the <see cref="String"/> type.</returns>
  433. public static string CreateInstanceOfString(Random rndGen, bool allowNull)
  434. {
  435. string result;
  436. do
  437. {
  438. result = CreateRandomString(rndGen, -1, null);
  439. }
  440. while (result == null && !allowNull);
  441. return result;
  442. }
  443. /// <summary>
  444. /// Creates an instance of the <see cref="String"/> type.
  445. /// </summary>
  446. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  447. /// <param name="size">The size of the string to be creted.</param>
  448. /// <param name="charsToUse">The characters to use when creating the string.</param>
  449. /// <returns>An instance of the <see cref="String"/> type.</returns>
  450. public static string CreateInstanceOfString(Random rndGen, int size, string charsToUse)
  451. {
  452. return CreateRandomString(rndGen, size, charsToUse);
  453. }
  454. /// <summary>
  455. /// Creates an instance of the <see cref="UInt16"/> type.
  456. /// </summary>
  457. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  458. /// <returns>An instance of the <see cref="UInt16"/> type.</returns>
  459. [CLSCompliant(false)]
  460. public static ushort CreateInstanceOfUInt16(Random rndGen)
  461. {
  462. byte[] rndValue = new byte[2];
  463. rndGen.NextBytes(rndValue);
  464. ushort result = 0;
  465. for (int i = 0; i < rndValue.Length; i++)
  466. {
  467. result = (ushort)(result << 8);
  468. result = (ushort)(result | (ushort)rndValue[i]);
  469. }
  470. return result;
  471. }
  472. /// <summary>
  473. /// Creates an instance of the <see cref="UInt32"/> type.
  474. /// </summary>
  475. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  476. /// <returns>An instance of the <see cref="UInt32"/> type.</returns>
  477. [CLSCompliant(false)]
  478. public static uint CreateInstanceOfUInt32(Random rndGen)
  479. {
  480. byte[] rndValue = new byte[4];
  481. rndGen.NextBytes(rndValue);
  482. uint result = 0;
  483. for (int i = 0; i < rndValue.Length; i++)
  484. {
  485. result = (uint)(result << 8);
  486. result = (uint)(result | (uint)rndValue[i]);
  487. }
  488. return result;
  489. }
  490. /// <summary>
  491. /// Creates an instance of the <see cref="UInt64"/> type.
  492. /// </summary>
  493. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  494. /// <returns>An instance of the <see cref="UInt64"/> type.</returns>
  495. [CLSCompliant(false)]
  496. public static ulong CreateInstanceOfUInt64(Random rndGen)
  497. {
  498. byte[] rndValue = new byte[8];
  499. rndGen.NextBytes(rndValue);
  500. ulong result = 0;
  501. for (int i = 0; i < rndValue.Length; i++)
  502. {
  503. result = (ulong)(result << 8);
  504. result = (ulong)(result | (ulong)rndValue[i]);
  505. }
  506. return result;
  507. }
  508. /// <summary>
  509. /// Creates an instance of the <see cref="Uri"/> type.
  510. /// </summary>
  511. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  512. /// <returns>An instance of the <see cref="Uri"/> type.</returns>
  513. public static System.Uri CreateInstanceOfUri(Random rndGen)
  514. {
  515. Uri result;
  516. UriKind kind;
  517. try
  518. {
  519. string uriString;
  520. do
  521. {
  522. uriString = UriCreator.CreateUri(rndGen, out kind);
  523. }
  524. while (IsRelativeIPv6Uri(uriString, kind));
  525. result = new Uri(uriString, kind);
  526. }
  527. catch (ArgumentException)
  528. {
  529. result = new Uri("my.schema://userName:password@my.domain/path1/path2?query1=123&query2=%22hello%22");
  530. }
  531. return result;
  532. }
  533. /// <summary>
  534. /// Creates an instance of the a string which represents an <see cref="Uri"/>.
  535. /// </summary>
  536. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  537. /// <returns>An instance of the a string which represents an <see cref="Uri"/>.</returns>
  538. public static string CreateInstanceOfUriString(Random rndGen)
  539. {
  540. UriKind kind;
  541. return UriCreator.CreateUri(rndGen, out kind);
  542. }
  543. /// <summary>
  544. /// Checks whether this creator can create an instance of the given type.
  545. /// </summary>
  546. /// <param name="type">The type to be created.</param>
  547. /// <returns><code>true</code> if this creator can create an instance of the given type; <code>false</code> otherwise.</returns>
  548. public static bool CanCreateInstanceOf(Type type)
  549. {
  550. return creators.ContainsKey(type);
  551. }
  552. /// <summary>
  553. /// Creates an instance of the given primitive type.
  554. /// </summary>
  555. /// <param name="type">The type to create an instance.</param>
  556. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  557. /// <returns>An instance of the given type.</returns>
  558. public static object CreatePrimitiveInstance(Type type, Random rndGen)
  559. {
  560. if (creators.ContainsKey(type))
  561. {
  562. return creators[type].Invoke(null, new object[] { rndGen });
  563. }
  564. else
  565. {
  566. throw new ArgumentException("Type " + type.FullName + " not supported");
  567. }
  568. }
  569. private static bool IsRelativeIPv6Uri(string uriString, UriKind kind)
  570. {
  571. return kind == UriKind.Relative && RelativeIPv6UriRegex.Match(uriString).Success;
  572. }
  573. /// <summary>
  574. /// Creates URI instances based on RFC 2396
  575. /// </summary>
  576. internal static class UriCreator
  577. {
  578. static readonly string digit;
  579. static readonly string upalpha;
  580. static readonly string lowalpha;
  581. static readonly string alpha;
  582. static readonly string alphanum;
  583. static readonly string hex;
  584. static readonly string mark;
  585. static readonly string unreserved;
  586. static readonly string reserved;
  587. static UriCreator()
  588. {
  589. digit = "0123456789";
  590. upalpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  591. lowalpha = upalpha.ToLower();
  592. alpha = upalpha + lowalpha;
  593. alphanum = alpha + digit;
  594. hex = digit + "ABCDEFabcdef";
  595. mark = "-_.!~*'()";
  596. unreserved = alphanum + mark;
  597. reserved = ";/?:@&=+$,";
  598. }
  599. internal static string CreateUri(Random rndGen, out UriKind kind)
  600. {
  601. StringBuilder sb = new StringBuilder();
  602. kind = UriKind.Relative;
  603. if (rndGen.Next(3) > 0)
  604. {
  605. // Add URI scheme
  606. CreateScheme(sb, rndGen);
  607. kind = UriKind.Absolute;
  608. }
  609. if (rndGen.Next(3) > 0)
  610. {
  611. // Add URI host
  612. sb.Append("//");
  613. if (rndGen.Next(10) == 0)
  614. {
  615. CreateUserInfo(sb, rndGen);
  616. }
  617. CreateHost(sb, rndGen);
  618. if (rndGen.Next(2) > 0)
  619. {
  620. sb.Append(':');
  621. sb.Append(rndGen.Next(65536));
  622. }
  623. }
  624. if (rndGen.Next(4) > 0)
  625. {
  626. // Add URI path
  627. for (int i = 0; i < rndGen.Next(1, 4); i++)
  628. {
  629. sb.Append('/');
  630. AddPathSegment(sb, rndGen);
  631. }
  632. }
  633. if (rndGen.Next(3) == 0)
  634. {
  635. // Add URI query string
  636. sb.Append('?');
  637. AddUriC(sb, rndGen);
  638. }
  639. return sb.ToString();
  640. }
  641. private static void CreateScheme(StringBuilder sb, Random rndGen)
  642. {
  643. int size = rndGen.Next(1, 10);
  644. AddChars(sb, rndGen, alpha, 1);
  645. string schemeChars = alpha + digit + "+-.";
  646. AddChars(sb, rndGen, schemeChars, size);
  647. sb.Append(':');
  648. }
  649. private static void CreateIPv4Address(StringBuilder sb, Random rndGen)
  650. {
  651. for (int i = 0; i < 4; i++)
  652. {
  653. if (i > 0)
  654. {
  655. sb.Append('.');
  656. }
  657. sb.Append(rndGen.Next(1000));
  658. }
  659. }
  660. private static void AddIPv6AddressPart(StringBuilder sb, Random rndGen)
  661. {
  662. int size = rndGen.Next(1, 10);
  663. if (size > 4)
  664. {
  665. size = 4;
  666. }
  667. AddChars(sb, rndGen, hex, size);
  668. }
  669. private static void CreateIPv6Address(StringBuilder sb, Random rndGen)
  670. {
  671. sb.Append('[');
  672. int temp = rndGen.Next(6);
  673. int i;
  674. switch (temp)
  675. {
  676. case 0:
  677. sb.Append("::");
  678. break;
  679. case 1:
  680. sb.Append("::1");
  681. break;
  682. case 2:
  683. sb.Append("FF01::101");
  684. break;
  685. case 3:
  686. sb.Append("::1");
  687. break;
  688. case 4:
  689. for (i = 0; i < 3; i++)
  690. {
  691. AddIPv6AddressPart(sb, rndGen);
  692. sb.Append(':');
  693. }
  694. for (i = 0; i < 3; i++)
  695. {
  696. sb.Append(':');
  697. AddIPv6AddressPart(sb, rndGen);
  698. }
  699. break;
  700. default:
  701. for (i = 0; i < 8; i++)
  702. {
  703. if (i > 0)
  704. {
  705. sb.Append(':');
  706. }
  707. AddIPv6AddressPart(sb, rndGen);
  708. }
  709. break;
  710. }
  711. sb.Append(']');
  712. }
  713. private static void AddChars(StringBuilder sb, Random rndGen, string validChars, int size)
  714. {
  715. for (int i = 0; i < size; i++)
  716. {
  717. sb.Append(validChars[rndGen.Next(validChars.Length)]);
  718. }
  719. }
  720. private static void CreateHostName(StringBuilder sb, Random rndGen)
  721. {
  722. int domainLabelCount = rndGen.Next(4);
  723. int size;
  724. for (int i = 0; i < domainLabelCount; i++)
  725. {
  726. AddChars(sb, rndGen, alphanum, 1);
  727. size = rndGen.Next(10) - 1;
  728. if (size > 0)
  729. {
  730. AddChars(sb, rndGen, alphanum + "-", size);
  731. AddChars(sb, rndGen, alphanum, 1);
  732. }
  733. sb.Append('.');
  734. }
  735. AddChars(sb, rndGen, alpha, 1);
  736. size = rndGen.Next(10) - 1;
  737. if (size > 0)
  738. {
  739. AddChars(sb, rndGen, alphanum + "-", size);
  740. AddChars(sb, rndGen, alphanum, 1);
  741. }
  742. }
  743. private static void CreateHost(StringBuilder sb, Random rndGen)
  744. {
  745. int temp = rndGen.Next(3);
  746. switch (temp)
  747. {
  748. case 0:
  749. CreateIPv4Address(sb, rndGen);
  750. break;
  751. case 1:
  752. CreateIPv6Address(sb, rndGen);
  753. break;
  754. case 2:
  755. CreateHostName(sb, rndGen);
  756. break;
  757. }
  758. }
  759. private static void CreateUserInfo(StringBuilder sb, Random rndGen)
  760. {
  761. AddChars(sb, rndGen, alpha, rndGen.Next(1, 10));
  762. if (rndGen.Next(3) > 0)
  763. {
  764. sb.Append(':');
  765. AddChars(sb, rndGen, alpha, rndGen.Next(1, 10));
  766. }
  767. sb.Append('@');
  768. }
  769. private static void AddEscapedChar(StringBuilder sb, Random rndGen)
  770. {
  771. sb.Append('%');
  772. AddChars(sb, rndGen, hex, 2);
  773. }
  774. private static void AddPathSegment(StringBuilder sb, Random rndGen)
  775. {
  776. string pchar = unreserved + ":@&=+$,";
  777. int size = rndGen.Next(1, 10);
  778. for (int i = 0; i < size; i++)
  779. {
  780. if (rndGen.Next(pchar.Length + 1) > 0)
  781. {
  782. AddChars(sb, rndGen, pchar, 1);
  783. }
  784. else
  785. {
  786. AddEscapedChar(sb, rndGen);
  787. }
  788. }
  789. }
  790. private static void AddUriC(StringBuilder sb, Random rndGen)
  791. {
  792. int size = rndGen.Next(20);
  793. string reservedPlusUnreserved = reserved + unreserved;
  794. for (int i = 0; i < size; i++)
  795. {
  796. if (rndGen.Next(5) > 0)
  797. {
  798. AddChars(sb, rndGen, reservedPlusUnreserved, 1);
  799. }
  800. else
  801. {
  802. AddEscapedChar(sb, rndGen);
  803. }
  804. }
  805. }
  806. }
  807. }
  808. /// <summary>
  809. /// Utility class used to create test instances of arbitrary types.
  810. /// </summary>
  811. public static class InstanceCreator
  812. {
  813. private static Stack<Type> typesInCreationStack = new Stack<Type>();
  814. /// <summary>
  815. /// Creates an instance of an array type.
  816. /// </summary>
  817. /// <param name="arrayType">The array type.</param>
  818. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  819. /// <returns>An instance of the given array type.</returns>
  820. public static object CreateInstanceOfArray(Type arrayType, Random rndGen)
  821. {
  822. Type type = arrayType.GetElementType();
  823. double rndNumber = rndGen.NextDouble();
  824. if (rndNumber < CreatorSettings.NullValueProbability)
  825. {
  826. return null; // 1% chance of null value
  827. }
  828. int size = (int)Math.Pow(CreatorSettings.MaxArrayLength, rndNumber); // this will create more small arrays than large ones
  829. size--;
  830. Array result = Array.CreateInstance(type, size);
  831. for (int i = 0; i < size; i++)
  832. {
  833. result.SetValue(CreateInstanceOf(type, rndGen), i);
  834. }
  835. return result;
  836. }
  837. /// <summary>
  838. /// Creates an instance of a <see cref="List{T}"/>.
  839. /// </summary>
  840. /// <param name="listType">The List&lt;T&gt; type.</param>
  841. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  842. /// <returns>An instance of the given list type.</returns>
  843. public static object CreateInstanceOfListOfT(Type listType, Random rndGen)
  844. {
  845. Type type = listType.GetGenericArguments()[0];
  846. double rndNumber = rndGen.NextDouble();
  847. if (rndNumber < CreatorSettings.NullValueProbability)
  848. {
  849. return null; // 1% chance of null value
  850. }
  851. int size = (int)Math.Pow(CreatorSettings.MaxListLength, rndNumber); // this will create more small lists than large ones
  852. size--;
  853. object result = Activator.CreateInstance(listType);
  854. MethodInfo addMethod = listType.GetMethod("Add");
  855. for (int i = 0; i < size; i++)
  856. {
  857. addMethod.Invoke(result, new object[] { CreateInstanceOf(type, rndGen) });
  858. }
  859. return result;
  860. }
  861. /// <summary>
  862. /// Creates an instance of a <see cref="LinkedList{T}"/>.
  863. /// </summary>
  864. /// <param name="listType">The LinkedList&lt;T&gt; type.</param>
  865. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  866. /// <returns>An instance of the given list type.</returns>
  867. public static object CreateInstanceOfLinkedListOfT(Type listType, Random rndGen)
  868. {
  869. Type type = listType.GetGenericArguments()[0];
  870. double rndNumber = rndGen.NextDouble();
  871. if (rndNumber < CreatorSettings.NullValueProbability)
  872. {
  873. return null; // 1% chance of null value
  874. }
  875. int size = (int)Math.Pow(CreatorSettings.MaxListLength, rndNumber); // this will create more small lists than large ones
  876. size--;
  877. object result = Activator.CreateInstance(listType);
  878. MethodInfo addMethod = listType.GetMethod("AddLast", new Type[] { type });
  879. for (int i = 0; i < size; i++)
  880. {
  881. addMethod.Invoke(result, new object[] { CreateInstanceOf(type, rndGen) });
  882. }
  883. return result;
  884. }
  885. /// <summary>
  886. /// Creates an instance of a <see cref="IEnumerable{T}"/>.
  887. /// </summary>
  888. /// <param name="enumerableOfTType">The IEnumerable&lt;T&gt; type.</param>
  889. /// <param name="enumeredType">The type to be enumerated.</param>
  890. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  891. /// <returns>An instance of the given enumerable type.</returns>
  892. public static object CreateInstanceOfIEnumerableOfT(Type enumerableOfTType, Type enumeredType, Random rndGen)
  893. {
  894. double rndNumber = rndGen.NextDouble();
  895. if (!enumerableOfTType.IsValueType && rndNumber < CreatorSettings.NullValueProbability)
  896. {
  897. return null; // 1% chance of null value
  898. }
  899. int size = (int)Math.Pow(CreatorSettings.MaxListLength, rndNumber); // this will create more small lists than large ones
  900. size--;
  901. object result = Activator.CreateInstance(enumerableOfTType);
  902. MethodInfo addMethod = enumerableOfTType.GetMethod("Add", new Type[] { enumeredType });
  903. if (addMethod == null)
  904. {
  905. throw new ArgumentException("Cannot create an instance of an IEnumerable<T> type which does not have a public Add method");
  906. }
  907. for (int i = 0; i < size; i++)
  908. {
  909. addMethod.Invoke(result, new object[] { CreateInstanceOf(enumeredType, rndGen) });
  910. }
  911. return result;
  912. }
  913. /// <summary>
  914. /// Creates an instance of a <see cref="Nullable{T}"/>.
  915. /// </summary>
  916. /// <param name="nullableOfTType">The Nullable&lt;T&gt; type.</param>
  917. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  918. /// <returns>An instance of the given nullable type.</returns>
  919. public static object CreateInstanceOfNullableOfT(Type nullableOfTType, Random rndGen)
  920. {
  921. if (rndGen.Next(5) == 0)
  922. {
  923. return null;
  924. }
  925. Type type = nullableOfTType.GetGenericArguments()[0];
  926. return CreateInstanceOf(type, rndGen);
  927. }
  928. /// <summary>
  929. /// Creates an instance of an enum type..
  930. /// </summary>
  931. /// <param name="enumType">The enum type.</param>
  932. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  933. /// <returns>An instance of the given enum type.</returns>
  934. public static object CreateInstanceOfEnum(Type enumType, Random rndGen)
  935. {
  936. bool hasFlags = enumType.GetCustomAttributes(typeof(FlagsAttribute), true).Length > 0;
  937. Array possibleValues = Enum.GetValues(enumType);
  938. if (possibleValues.Length == 0)
  939. {
  940. return 0;
  941. }
  942. if (!hasFlags)
  943. {
  944. return possibleValues.GetValue(rndGen.Next(possibleValues.Length));
  945. }
  946. else
  947. {
  948. Type underlyingType = Enum.GetUnderlyingType(enumType);
  949. string strResult;
  950. if (underlyingType.FullName == typeof(ulong).FullName)
  951. {
  952. ulong result = 0;
  953. if (rndGen.Next(10) > 0)
  954. {
  955. // 10% chance of value zero
  956. foreach (object value in possibleValues)
  957. {
  958. if (rndGen.Next(2) == 0)
  959. {
  960. result |= ((IConvertible)value).ToUInt64(null);
  961. }
  962. }
  963. }
  964. strResult = result.ToString();
  965. }
  966. else
  967. {
  968. long result = 0;
  969. if (rndGen.Next(10) > 0)
  970. {
  971. // 10% chance of value zero
  972. foreach (object value in possibleValues)
  973. {
  974. if (rndGen.Next(2) == 0)
  975. {
  976. result |= ((IConvertible)value).ToInt64(null);
  977. }
  978. }
  979. }
  980. strResult = result.ToString();
  981. }
  982. return Enum.Parse(enumType, strResult, true);
  983. }
  984. }
  985. /// <summary>
  986. /// Creates an instance of a <see cref="Dictionary{K,V}"/>.
  987. /// </summary>
  988. /// <param name="dictionaryType">The Dictionary&lt;K,V&gt; type.</param>
  989. /// <param name="rndGen">A <see cref="Random"/> used to create the instance.</param>
  990. /// <returns>An instance of the given dictionary type.</returns>
  991. public static object CreateInstanceOfDictionaryOfKAndV(Type dictionaryType, Random rndGen)
  992. {
  993. Type[] genericArgs = dictionaryType.GetGenericArguments();
  994. Type typeK = genericArgs[0];
  995. Type typeV = genericArgs[1];
  996. double rndNumber = rndGen.NextDouble();
  997. if (rndNumber < CreatorSettings.NullValueProbability)
  998. {
  999. return null; // 1% chance of null value
  1000. }
  1001. int size = (int)Math.Pow(CreatorSettings.MaxListLength, rndNumber); // this will create more small dictionaries than large ones
  1002. size--;
  1003. object result = Activator.CreateInstance(dictionaryType);
  1004. MethodInfo addMethod = dictionaryType.GetMethod("Add");
  1005. MethodInfo containsKeyMethod = dictionaryType.GetMethod("ContainsKey");
  1006. for (int i = 0; i < size; i++)
  1007. {
  1008. object newKey;
  1009. do
  1010. {
  1011. newKey = CreateInstanceOf(typeK, rndGen);
  1012. }
  1013. while (newKey == null);
  1014. bool containsKey = (bool)containsKeyMethod.Invoke(result, new object[] { newKey });
  1015. if (!containsKey)
  1016. {
  1017. object newValue = CreateInstanceOf(typeV, rndGen);
  1018. addMethod.Invoke(result, new object[] { newKey, newValue });
  1019. }
  1020. }
  1021. return result;
  1022. }
  1023. /// <summary>
  1024. /// Creates an instance of the given type.
  1025. /// </summary>
  1026. /// <typeparam name="T">The type to create an instance from.</typeparam>
  1027. /// <param name="rndGen">A random generator used to populate the instance.</param>
  1028. /// <returns>An instance of the given type.</returns>
  1029. public static T CreateInstanceOf<T>(Random rndGen)
  1030. {
  1031. return (T)InstanceCreator.CreateInstanceOf(typeof(T), rndGen);
  1032. }
  1033. /// <summary>
  1034. /// Creates an instance of the given type.
  1035. /// </summary>
  1036. /// <param name="type">The type to create an instance from.</param>
  1037. /// <param name="rndGen">A random generator used to populate the instance.</param>
  1038. /// <param name="allowNulls">A flag indicating whether null values can be returned by this method.</param>
  1039. /// <returns>An instance of the given type.</returns>
  1040. public static object CreateInstanceOf(Type type, Random rndGen, bool allowNulls)
  1041. {
  1042. double currentNullProbability = CreatorSettings.NullValueProbability;
  1043. if (!allowNulls)
  1044. {
  1045. CreatorSettings.NullValueProbability = 0;
  1046. }
  1047. object result = CreateInstanceOf(type, rndGen);
  1048. if (!allowNulls)
  1049. {
  1050. CreatorSettings.NullValueProbability = currentNullProbability;
  1051. }
  1052. return result;
  1053. }
  1054. /// <summary>
  1055. /// Creates an instance of the given type.
  1056. /// </summary>
  1057. /// <param name="type">The type to create an instance from.</param>
  1058. /// <param name="rndGen">A random generator used to populate the instance.</param>
  1059. /// <returns>An instance of the given type.</returns>
  1060. public static object CreateInstanceOf(Type type, Random rndGen)
  1061. {
  1062. if (CreatorSettings.CreatorSurrogate != null)
  1063. {
  1064. if (CreatorSettings.CreatorSurrogate.CanCreateInstanceOf(type))
  1065. {
  1066. return CreatorSettings.CreatorSurrogate.CreateInstanceOf(type, rndGen);
  1067. }
  1068. }
  1069. ConstructorInfo randomConstructor = type.GetConstructor(new Type[] { typeof(Random) });
  1070. if (randomConstructor != null)
  1071. {
  1072. // it's possible that a class with a Type.GetConstructor will return a constructor
  1073. // which takes a System.Object; we only want to use if it really takes a Random argument.
  1074. ParameterInfo[] ctorParameters = randomConstructor.GetParameters();
  1075. if (ctorParameters.Length == 1 && ctorParameters[0].ParameterType == typeof(Random))
  1076. {
  1077. return randomConstructor.Invoke(new object[] { rndGen });
  1078. }
  1079. }
  1080. // Allow for a static factory method (called 'CreateInstance' to allow for inheritance scenarios
  1081. MethodInfo randomFactoryMethod = type.GetMethod("CreateInstance", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(Random) }, null);
  1082. if (randomFactoryMethod != null)
  1083. {
  1084. ParameterInfo[] methodParameters = randomFactoryMethod.GetParameters();
  1085. if (methodParameters.Length == 1 && methodParameters[0].ParameterType == typeof(Random))
  1086. {
  1087. return randomFactoryMethod.Invoke(null, new object[] { rndGen });
  1088. }
  1089. }
  1090. object result = null;
  1091. Type genericElementType = null;
  1092. if (CreatorSettings.AvoidStackOverflowDueToTypeCycles)
  1093. {
  1094. if (typesInCreationStack.Contains(type))
  1095. {
  1096. if (type.IsValueType)
  1097. {
  1098. return Activator.CreateInstance(type);
  1099. }
  1100. else
  1101. {
  1102. return null;
  1103. }
  1104. }
  1105. typesInCreationStack.Push(type);
  1106. }
  1107. if (PrimitiveCreator.CanCreateInstanceOf(type))
  1108. {
  1109. result = PrimitiveCreator.CreatePrimitiveInstance(type, rndGen);
  1110. }
  1111. else if (type.IsEnum)
  1112. {
  1113. result = CreateInstanceOfEnum(type, rndGen);
  1114. }
  1115. else if (type.IsArray)
  1116. {
  1117. result = CreateInstanceOfArray(type, rndGen);
  1118. }
  1119. else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
  1120. {