ConfigPropertyTests.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. using System.Collections.Concurrent;
  2. namespace UnitTests_Parallelizable.ConfigurationTests;
  3. public class ConfigPropertyTests
  4. {
  5. private class Dummy
  6. {
  7. public string Value { get; set; } = string.Empty;
  8. }
  9. [Fact]
  10. public void PropertyValue_CanBeSetAndReadConcurrently ()
  11. {
  12. var propertyInfo = typeof (Dummy).GetProperty (nameof (Dummy.Value));
  13. var configProperty = new ConfigProperty { PropertyInfo = propertyInfo };
  14. int numTasks = 20;
  15. var values = new string [numTasks];
  16. for (int i = 0; i < numTasks; i++)
  17. {
  18. values [i] = $"Value_{i}";
  19. }
  20. Parallel.For (0, numTasks, i =>
  21. {
  22. configProperty.PropertyValue = values [i];
  23. // Remove the per-thread assertion, as it is not valid in a concurrent context.
  24. // Optionally, you can check that the value is one of the expected values:
  25. var currentValue = configProperty.PropertyValue as string;
  26. Assert.Contains (currentValue, values);
  27. });
  28. }
  29. [Fact]
  30. public void UpdateFrom_CanBeCalledConcurrently ()
  31. {
  32. var propertyInfo = typeof (Dummy).GetProperty (nameof (Dummy.Value));
  33. var configProperty = new ConfigProperty { PropertyInfo = propertyInfo, PropertyValue = "Initial" };
  34. int numTasks = 20;
  35. Parallel.For (0, numTasks, i =>
  36. {
  37. var newValue = $"Thread_{i}";
  38. configProperty.UpdateFrom (newValue);
  39. });
  40. var finalValue = configProperty.PropertyValue as string;
  41. Assert.StartsWith ("Thread_", finalValue);
  42. }
  43. [Fact]
  44. public void DeepCloner_DeepClone_IsThreadSafe ()
  45. {
  46. var propertyInfo = typeof (Dummy).GetProperty (nameof (Dummy.Value));
  47. var configProperty = new ConfigProperty { PropertyInfo = propertyInfo, PropertyValue = "DeepCloneValue" };
  48. int numTasks = 20;
  49. Parallel.For (0, numTasks, i =>
  50. {
  51. var clone = DeepCloner.DeepClone (configProperty);
  52. Assert.NotSame (configProperty, clone);
  53. Assert.Equal ("DeepCloneValue", clone.PropertyValue);
  54. });
  55. }
  56. [Fact]
  57. public void ConcurrentDictionary_UpdateFrom_IsThreadSafe ()
  58. {
  59. var propertyInfo = typeof (Dummy).GetProperty (nameof (Dummy.Value));
  60. var destinationDict = new ConcurrentDictionary<string, ConfigProperty> (StringComparer.InvariantCultureIgnoreCase);
  61. destinationDict.TryAdd ("prop1", new ConfigProperty { PropertyValue = "Original", HasValue = true });
  62. var configProperty = new ConfigProperty
  63. {
  64. PropertyInfo = propertyInfo,
  65. PropertyValue = destinationDict
  66. };
  67. int numTasks = 20;
  68. Parallel.For (0, numTasks, i =>
  69. {
  70. var sourceDict = new ConcurrentDictionary<string, ConfigProperty> (StringComparer.InvariantCultureIgnoreCase);
  71. sourceDict.TryAdd ($"prop{i}", new ConfigProperty { PropertyValue = $"Value_{i}", HasValue = true });
  72. configProperty.UpdateFrom (sourceDict);
  73. });
  74. var resultDict = configProperty.PropertyValue as ConcurrentDictionary<string, ConfigProperty>;
  75. Assert.NotNull (resultDict);
  76. for (int i = 0; i < numTasks; i++)
  77. {
  78. Assert.True (resultDict!.ContainsKey ($"prop{i}"));
  79. Assert.Equal ($"Value_{i}", resultDict [$"prop{i}"].PropertyValue);
  80. }
  81. Assert.True (resultDict!.ContainsKey ("prop1"));
  82. }
  83. }