IntervalTests.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. using System;
  2. using Xunit;
  3. namespace MonoGame.Extended.Tests;
  4. public class IntervalTests
  5. {
  6. [Fact]
  7. public void Constructor_WithMinLessThanMax_CreatesProperInterval()
  8. {
  9. Interval<int> interval = new(10, 20);
  10. Assert.Equal(10, interval.Min);
  11. Assert.Equal(20, interval.Max);
  12. Assert.True(interval.IsProper);
  13. Assert.False(interval.IsDegenerate);
  14. Assert.False(interval.IsEmpty);
  15. }
  16. [Fact]
  17. public void Constructor_WithEqualBounds_CreatesDegenerateInterval()
  18. {
  19. Interval<int> interval = new(10, 10);
  20. Assert.Equal(10, interval.Min);
  21. Assert.Equal(10, interval.Max);
  22. Assert.False(interval.IsProper);
  23. Assert.True(interval.IsDegenerate);
  24. Assert.False(interval.IsEmpty);
  25. }
  26. [Fact]
  27. public void Constructor_WithInvalidBounds_ThrowsArgumentException()
  28. {
  29. Assert.Throws<ArgumentException>(() => new Interval<int>(20, 10));
  30. }
  31. [Fact]
  32. public void Constructor_SingleValue_CreatesDegenerate()
  33. {
  34. Interval<int> interval = new(10);
  35. Assert.Equal(10, interval.Min);
  36. Assert.Equal(10, interval.Max);
  37. Assert.True(interval.IsDegenerate);
  38. Assert.False(interval.IsProper);
  39. Assert.False(interval.IsEmpty);
  40. }
  41. [Fact]
  42. public void Empty_CreatesEmptyInterval()
  43. {
  44. Interval<int> empty = Interval<int>.Empty;
  45. Assert.True(empty.IsEmpty);
  46. Assert.False(empty.IsDegenerate);
  47. Assert.False(empty.IsProper);
  48. }
  49. [Fact]
  50. public void Empty_AccessingBounds_ThrowsInvalidOperationException()
  51. {
  52. Interval<int> empty = Interval<int>.Empty;
  53. Assert.Throws<InvalidOperationException>(() => empty.Min);
  54. Assert.Throws<InvalidOperationException>(() => empty.Max);
  55. }
  56. [Fact]
  57. public void Contains_Value_ReturnsTrueForBoundaryAndInteriorValues()
  58. {
  59. Interval<int> interval = new(10, 15);
  60. for (int i = 10; i <= 15; i++)
  61. {
  62. Assert.True(interval.Contains(i));
  63. }
  64. }
  65. [Fact]
  66. public void Contains_Value_ReturnsFalseForValuesOutsideBounds()
  67. {
  68. Interval<int> interval = new(10, 20);
  69. Assert.False(interval.Contains(9));
  70. Assert.False(interval.Contains(21));
  71. }
  72. [Fact]
  73. public void Contains_Value_EmptyInterval_ReturnsFalse()
  74. {
  75. Interval<int> empty = Interval<int>.Empty;
  76. Assert.False(empty.Contains(10));
  77. }
  78. [Fact]
  79. public void Contains_Interval_ReturnsTrueForCompletelyContainedInterval()
  80. {
  81. Interval<int> outer = new(10, 30);
  82. Interval<int> inner = new(15, 25);
  83. Assert.True(outer.Contains(inner));
  84. }
  85. [Fact]
  86. public void Contains_Interval_ReturnsFalseForPartiallyOverlappingInterval()
  87. {
  88. Interval<int> interval = new(10, 20);
  89. Interval<int> overlapping = new(15, 25);
  90. Assert.False(interval.Contains(overlapping));
  91. }
  92. [Fact]
  93. public void Contains_Interval_ReturnsFalseForSeparateInterval()
  94. {
  95. Interval<int> interval = new(10, 20);
  96. Interval<int> separate = new(30, 40);
  97. Assert.False(interval.Contains(separate));
  98. }
  99. [Fact]
  100. public void Contains_EmptyInterval_ReturnsTrue()
  101. {
  102. Interval<int> interval = new(10, 20);
  103. Interval<int> empty = Interval<int>.Empty;
  104. Assert.True(interval.Contains(empty));
  105. Assert.True(empty.Contains(empty));
  106. }
  107. [Fact]
  108. public void Contains_Self_ReturnsTrue()
  109. {
  110. Interval<int> interval = new(10, 20);
  111. Assert.True(interval.Contains(interval));
  112. }
  113. [Fact]
  114. public void Overlap_ReturnsTrueForOverlappingIntervals()
  115. {
  116. Interval<int> a = new(10, 20);
  117. Interval<int> b = new(15, 25);
  118. Assert.True(a.Overlap(b));
  119. Assert.True(b.Overlap(a));
  120. }
  121. [Fact]
  122. public void Overlap_ReturnsFalseForSeparateIntervals()
  123. {
  124. Interval<int> a = new(10, 20);
  125. Interval<int> c = new(30, 40);
  126. Assert.False(a.Overlap(c));
  127. Assert.False(c.Overlap(a));
  128. }
  129. [Fact]
  130. public void Overlap_ReturnsTrueForIntervalsTouchingAtBoundary()
  131. {
  132. Interval<int> a = new(10, 20);
  133. Interval<int> d = new(20, 30);
  134. Assert.True(a.Overlap(d));
  135. }
  136. [Fact]
  137. public void Overlap_WithEmptyInterval_ReturnsFalse()
  138. {
  139. Interval<int> interval = new(10, 20);
  140. Interval<int> empty = Interval<int>.Empty;
  141. Assert.False(interval.Overlap(empty));
  142. Assert.False(empty.Overlap(empty));
  143. }
  144. [Fact]
  145. public void Overlap_Self_ReturnsTrue()
  146. {
  147. Interval<int> interval = new(10, 20);
  148. Assert.True(interval.Overlap(interval));
  149. }
  150. [Fact]
  151. public void Intersect_OverlappingIntervals_ReturnsCorrectBounds()
  152. {
  153. Interval<int> a = new(10, 20);
  154. Interval<int> b = new(15, 25);
  155. Interval<int> intersection = a.Intersect(b);
  156. Assert.Equal(15, intersection.Min);
  157. Assert.Equal(20, intersection.Max);
  158. }
  159. [Fact]
  160. public void Intersect_NoOverlap_ReturnsEmpty()
  161. {
  162. Interval<int> a = new(10, 20);
  163. Interval<int> b = new(30, 40);
  164. Assert.True(a.Intersect(b).IsEmpty);
  165. }
  166. [Fact]
  167. public void Intersect_WithEmptyInterval_ReturnsEmpty()
  168. {
  169. Interval<int> interval = new(10, 20);
  170. Interval<int> empty = Interval<int>.Empty;
  171. Assert.True(interval.Intersect(empty).IsEmpty);
  172. Assert.True(empty.Intersect(empty).IsEmpty);
  173. }
  174. [Fact]
  175. public void Intersect_Self_ReturnsOriginalInterval()
  176. {
  177. Interval<int> interval = new(10, 20);
  178. Assert.Equal(interval, interval.Intersect(interval));
  179. }
  180. [Fact]
  181. public void Hull_SeparateIntervals_ReturnsSpanningInterval()
  182. {
  183. Interval<int> a = new(10, 20);
  184. Interval<int> b = new(30, 40);
  185. Interval<int> hull = a.Hull(b);
  186. Assert.Equal(10, hull.Min);
  187. Assert.Equal(40, hull.Max);
  188. }
  189. [Fact]
  190. public void Hull_WithEmptyInterval_ReturnsNonEmptyInterval()
  191. {
  192. Interval<int> interval = new(10, 20);
  193. Interval<int> empty = Interval<int>.Empty;
  194. Assert.Equal(interval, interval.Hull(empty));
  195. Assert.Equal(interval, empty.Hull(interval));
  196. Assert.True(empty.Hull(empty).IsEmpty);
  197. }
  198. [Fact]
  199. public void Hull_Self_ReturnsOriginalInterval()
  200. {
  201. Interval<int> interval = new(10, 20);
  202. Assert.Equal(interval, interval.Hull(interval));
  203. }
  204. [Fact]
  205. public void Hull_StaticMethod_HandlesParameterOrderCorrectly()
  206. {
  207. Interval<int> hull1 = Interval<int>.Hull(20, 10);
  208. Interval<int> hull2 = Interval<int>.Hull(10, 20);
  209. Assert.Equal(10, hull1.Min);
  210. Assert.Equal(20, hull1.Max);
  211. Assert.Equal(hull1, hull2);
  212. }
  213. [Fact]
  214. public void Equality_SameIntervals_ReturnsTrue()
  215. {
  216. Interval<int> a = new(10, 20);
  217. Interval<int> b = new(10, 20);
  218. Assert.True(a == b);
  219. Assert.True(a.Equals(b));
  220. Assert.False(a != b);
  221. }
  222. [Fact]
  223. public void Equality_DifferentIntervals_ReturnsFalse()
  224. {
  225. Interval<int> a = new(10, 20);
  226. Interval<int> c = new(20, 30);
  227. Assert.False(a == c);
  228. Assert.False(a.Equals(c));
  229. Assert.True(a != c);
  230. }
  231. [Fact]
  232. public void Equality_EmptyIntervals_ReturnsTrue()
  233. {
  234. Interval<int> empty1 = Interval<int>.Empty;
  235. Interval<int> empty2 = Interval<int>.Empty;
  236. Assert.True(empty1 == empty2);
  237. Assert.True(empty1.Equals(empty2));
  238. }
  239. [Fact]
  240. public void Equality_EmptyVsNonEmpty_ReturnsFalse()
  241. {
  242. Interval<int> interval = new(10, 20);
  243. Interval<int> empty = Interval<int>.Empty;
  244. Assert.False(interval == empty);
  245. Assert.True(interval != empty);
  246. }
  247. [Fact]
  248. public void GetHashCode_EqualIntervals_ReturnsSameHashCode()
  249. {
  250. Interval<int> a = new(10, 20);
  251. Interval<int> b = new(10, 20);
  252. Assert.Equal(a.GetHashCode(), b.GetHashCode());
  253. }
  254. [Fact]
  255. public void ImplicitConversion_FromValue_CreatesDegenerate()
  256. {
  257. Interval<int> interval = 10;
  258. Assert.Equal(10, interval.Min);
  259. Assert.Equal(10, interval.Max);
  260. Assert.True(interval.IsDegenerate);
  261. }
  262. [Fact]
  263. public void ToString_ShowsCorrectFormat()
  264. {
  265. Assert.Equal("[10, 20]", new Interval<int>(10, 20).ToString());
  266. Assert.Equal("[10]", new Interval<int>(10).ToString());
  267. Assert.Equal("∅", Interval<int>.Empty.ToString());
  268. }
  269. [Fact]
  270. public void StringInterval_WorksWithComparable()
  271. {
  272. Interval<string> interval = new("apple", "zebra");
  273. Assert.True(interval.Contains("banana"));
  274. Assert.False(interval.Contains("aardvark"));
  275. }
  276. }