1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using System.Collections; 7 using System.Collections.Generic; 8 using System.Collections.ObjectModel; 9 using System.Runtime.CompilerServices; 10 using Xunit; 11 12 namespace System.Linq.Expressions.Tests 13 { 14 public class ReadOnlyCollectionBuilderTests 15 { 16 [Fact] ReadOnlyCollectionBuilder_Ctor_Default()17 public void ReadOnlyCollectionBuilder_Ctor_Default() 18 { 19 var rocb = new ReadOnlyCollectionBuilder<int>(); 20 21 Assert.Equal(0, rocb.Capacity); 22 23 AssertEmpty(rocb); 24 } 25 26 [Theory] 27 [InlineData(-2)] 28 [InlineData(-1)] ReadOnlyCollectionBuilder_Ctor_Capacity_ArgumentChecking(int capacity)29 public void ReadOnlyCollectionBuilder_Ctor_Capacity_ArgumentChecking(int capacity) 30 { 31 AssertExtensions.Throws<ArgumentOutOfRangeException>("capacity", () => new ReadOnlyCollectionBuilder<int>(capacity)); 32 } 33 34 [Theory] 35 [InlineData(0)] 36 [InlineData(1)] 37 [InlineData(2)] ReadOnlyCollectionBuilder_Ctor_Capacity(int capacity)38 public void ReadOnlyCollectionBuilder_Ctor_Capacity(int capacity) 39 { 40 var rocb = new ReadOnlyCollectionBuilder<int>(capacity); 41 42 Assert.Equal(capacity, rocb.Capacity); 43 44 AssertEmpty(rocb); 45 } 46 47 [Fact] ReadOnlyCollectionBuilder_Ctor_Collection_ArgumentChecking()48 public void ReadOnlyCollectionBuilder_Ctor_Collection_ArgumentChecking() 49 { 50 AssertExtensions.Throws<ArgumentNullException>("collection", () => new ReadOnlyCollectionBuilder<int>(null)); 51 } 52 53 [Theory] 54 [MemberData(nameof(InitialCollections))] ReadOnlyCollectionBuilder_Ctor_Collection(IEnumerable<int> collection)55 public void ReadOnlyCollectionBuilder_Ctor_Collection(IEnumerable<int> collection) 56 { 57 var rocb = new ReadOnlyCollectionBuilder<int>(collection); 58 59 Assert.Equal(collection.Count(), rocb.Count); 60 Assert.True(collection.SequenceEqual(rocb)); 61 62 int[] array = rocb.ToArray(); 63 64 Assert.Equal(collection.Count(), array.Length); 65 Assert.True(collection.SequenceEqual(array)); 66 67 ReadOnlyCollection<int> roc = rocb.ToReadOnlyCollection(); 68 69 Assert.Equal(collection.Count(), roc.Count); 70 Assert.True(collection.SequenceEqual(roc)); 71 72 AssertEmpty(rocb); // ToReadOnlyCollection behavior is to empty the builder 73 } 74 75 [Fact] ReadOnlyCollectionBuilder_Capacity1()76 public void ReadOnlyCollectionBuilder_Capacity1() 77 { 78 var rocb = new ReadOnlyCollectionBuilder<int>(); 79 80 Assert.Equal(0, rocb.Capacity); 81 Assert.Equal(0, rocb.Count); 82 83 Assert.Throws<ArgumentOutOfRangeException>(() => rocb.Capacity = -1); 84 85 rocb.Capacity = 0; 86 87 Assert.Equal(0, rocb.Capacity); 88 Assert.Equal(0, rocb.Count); 89 90 rocb.Capacity = 1; 91 92 Assert.Equal(1, rocb.Capacity); 93 Assert.Equal(0, rocb.Count); 94 95 rocb.Capacity = 2; 96 97 Assert.Equal(2, rocb.Capacity); 98 Assert.Equal(0, rocb.Count); 99 } 100 101 [Fact] ReadOnlyCollectionBuilder_Capacity2()102 public void ReadOnlyCollectionBuilder_Capacity2() 103 { 104 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1 }); 105 106 Assert.Equal(1, rocb.Capacity); 107 Assert.Equal(1, rocb.Count); 108 109 AssertExtensions.Throws<ArgumentOutOfRangeException>("value", () => { rocb.Capacity = 0; }); 110 AssertExtensions.Throws<ArgumentOutOfRangeException>("value", () => { rocb.Capacity = -1; }); 111 112 rocb.Capacity = 1; 113 114 Assert.Equal(1, rocb.Capacity); 115 Assert.Equal(1, rocb.Count); 116 117 rocb.Capacity = 2; 118 119 Assert.Equal(2, rocb.Capacity); 120 Assert.Equal(1, rocb.Count); 121 } 122 123 [Fact] ReadOnlyCollectionBuilder_Capacity3()124 public void ReadOnlyCollectionBuilder_Capacity3() 125 { 126 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1 }); 127 128 Assert.Equal(1, rocb.Capacity); 129 Assert.Equal(1, rocb.Count); 130 131 rocb.RemoveAt(0); 132 133 Assert.Equal(1, rocb.Capacity); 134 Assert.Equal(0, rocb.Count); 135 136 rocb.Capacity = 0; 137 138 Assert.Equal(0, rocb.Capacity); 139 Assert.Equal(0, rocb.Count); 140 } 141 142 [Fact] ReadOnlyCollectionBuilder_IList_IsReadOnly()143 public void ReadOnlyCollectionBuilder_IList_IsReadOnly() 144 { 145 IList rocb = new ReadOnlyCollectionBuilder<int>(); 146 147 Assert.False(rocb.IsReadOnly); 148 } 149 150 [Fact] ReadOnlyCollectionBuilder_ICollectionOfT_IsReadOnly()151 public void ReadOnlyCollectionBuilder_ICollectionOfT_IsReadOnly() 152 { 153 ICollection<int> rocb = new ReadOnlyCollectionBuilder<int>(); 154 155 Assert.False(rocb.IsReadOnly); 156 } 157 158 [Fact] ReadOnlyCollectionBuilder_IList_IsFixedSize()159 public void ReadOnlyCollectionBuilder_IList_IsFixedSize() 160 { 161 IList rocb = new ReadOnlyCollectionBuilder<int>(); 162 163 Assert.False(rocb.IsFixedSize); 164 } 165 166 [Fact] ReadOnlyCollectionBuilder_IList_IsSynchronized()167 public void ReadOnlyCollectionBuilder_IList_IsSynchronized() 168 { 169 ICollection rocb = new ReadOnlyCollectionBuilder<int>(); 170 171 Assert.False(rocb.IsSynchronized); 172 } 173 174 [Fact] ReadOnlyCollectionBuilder_ICollection_SyncRoot()175 public void ReadOnlyCollectionBuilder_ICollection_SyncRoot() 176 { 177 ICollection rocb = new ReadOnlyCollectionBuilder<int>(); 178 179 object root1 = rocb.SyncRoot; 180 Assert.NotNull(root1); 181 182 object root2 = rocb.SyncRoot; 183 Assert.Same(root1, root2); 184 } 185 186 [Fact] ReadOnlyCollectionBuilder_IndexOf()187 public void ReadOnlyCollectionBuilder_IndexOf() 188 { 189 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 2, 3 }); 190 191 Assert.Equal(4, rocb.Count); 192 193 Assert.Equal(0, rocb.IndexOf(1)); 194 Assert.Equal(1, rocb.IndexOf(2)); 195 Assert.Equal(3, rocb.IndexOf(3)); 196 197 Assert.InRange(rocb.IndexOf(0), int.MinValue, -1); 198 Assert.InRange(rocb.IndexOf(4), int.MinValue, -1); 199 200 rocb.Capacity = 5; 201 202 Assert.Equal(4, rocb.Count); 203 Assert.InRange(rocb.IndexOf(0), int.MinValue, -1); // No default values leak in through underlying array 204 205 Assert.True(rocb.Remove(3)); 206 207 Assert.Equal(3, rocb.Count); 208 Assert.InRange(rocb.IndexOf(0), int.MinValue, -1); // No default values leak in through underlying array 209 Assert.InRange(rocb.IndexOf(3), int.MinValue, -1); 210 } 211 212 [Fact] ReadOnlyCollectionBuilder_IList_IndexOf()213 public void ReadOnlyCollectionBuilder_IList_IndexOf() 214 { 215 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 2, 3 }); 216 IList list = rocb; 217 218 Assert.Equal(4, list.Count); 219 220 Assert.Equal(0, list.IndexOf(1)); 221 Assert.Equal(1, list.IndexOf(2)); 222 Assert.Equal(3, list.IndexOf(3)); 223 224 Assert.InRange(list.IndexOf(0), int.MinValue, -1); 225 Assert.InRange(list.IndexOf(4), int.MinValue, -1); 226 227 rocb.Capacity = 5; 228 229 Assert.Equal(4, list.Count); 230 Assert.InRange(list.IndexOf(0), int.MinValue, -1); // No default values leak in through underlying array 231 232 list.Remove(3); 233 234 Assert.Equal(3, list.Count); 235 Assert.InRange(list.IndexOf(0), int.MinValue, -1); // No default values leak in through underlying array 236 Assert.InRange(list.IndexOf(3), int.MinValue, -1); 237 238 Assert.InRange(list.IndexOf("bar"), int.MinValue, -1); 239 Assert.InRange(list.IndexOf(null), int.MinValue, -1); 240 } 241 242 [Fact] ReadOnlyCollectionBuilder_Insert()243 public void ReadOnlyCollectionBuilder_Insert() 244 { 245 var rocb = new ReadOnlyCollectionBuilder<int>(); 246 247 Assert.Equal(0, rocb.Count); 248 249 Assert.Throws<ArgumentOutOfRangeException>(() => rocb.Insert(-1, 1)); 250 AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => rocb.Insert(1, 1)); 251 252 rocb.Insert(0, 1); 253 254 Assert.True(new[] { 1 }.SequenceEqual(rocb)); 255 256 rocb.Insert(0, 2); 257 258 Assert.True(new[] { 2, 1 }.SequenceEqual(rocb)); 259 260 rocb.Insert(0, 3); 261 262 Assert.True(new[] { 3, 2, 1 }.SequenceEqual(rocb)); 263 264 rocb.Insert(1, 4); 265 266 Assert.True(new[] { 3, 4, 2, 1 }.SequenceEqual(rocb)); 267 268 rocb.Insert(4, 5); 269 270 Assert.True(new[] { 3, 4, 2, 1, 5 }.SequenceEqual(rocb)); 271 } 272 273 [Fact] ReadOnlyCollectionBuilder_IList_Insert()274 public void ReadOnlyCollectionBuilder_IList_Insert() 275 { 276 IList rocb = new ReadOnlyCollectionBuilder<int>(); 277 278 Assert.Equal(0, rocb.Count); 279 280 Assert.Throws<ArgumentOutOfRangeException>(() => rocb.Insert(-1, 1)); 281 AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => rocb.Insert(1, 1)); 282 283 AssertExtensions.Throws<ArgumentException>("value", () => rocb.Insert(1, "bar")); 284 AssertExtensions.Throws<ArgumentException>("value", () => rocb.Insert(1, null)); 285 286 rocb.Insert(0, 1); 287 288 Assert.True(new[] { 1 }.SequenceEqual(rocb.Cast<int>())); 289 290 rocb.Insert(0, 2); 291 292 Assert.True(new[] { 2, 1 }.SequenceEqual(rocb.Cast<int>())); 293 294 rocb.Insert(0, 3); 295 296 Assert.True(new[] { 3, 2, 1 }.SequenceEqual(rocb.Cast<int>())); 297 298 rocb.Insert(1, 4); 299 300 Assert.True(new[] { 3, 4, 2, 1 }.SequenceEqual(rocb.Cast<int>())); 301 302 rocb.Insert(4, 5); 303 304 Assert.True(new[] { 3, 4, 2, 1, 5 }.SequenceEqual(rocb.Cast<int>())); 305 } 306 307 [Fact] ReadOnlyCollectionBuilder_RemoveAt()308 public void ReadOnlyCollectionBuilder_RemoveAt() 309 { 310 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3, 4 }); 311 312 Assert.True(new[] { 1, 2, 3, 4 }.SequenceEqual(rocb)); 313 314 AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => rocb.RemoveAt(-1)); 315 AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => rocb.RemoveAt(4)); 316 317 rocb.RemoveAt(0); 318 319 Assert.True(new[] { 2, 3, 4 }.SequenceEqual(rocb)); 320 AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => rocb.RemoveAt(3)); 321 322 rocb.RemoveAt(1); 323 324 Assert.True(new[] { 2, 4 }.SequenceEqual(rocb)); 325 AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => rocb.RemoveAt(2)); 326 327 rocb.RemoveAt(1); 328 329 Assert.True(new[] { 2 }.SequenceEqual(rocb)); 330 AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => rocb.RemoveAt(1)); 331 332 rocb.RemoveAt(0); 333 334 Assert.Equal(0, rocb.Count); 335 AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => rocb.RemoveAt(0)); 336 } 337 338 [Fact] ReadOnlyCollectionBuilder_Remove()339 public void ReadOnlyCollectionBuilder_Remove() 340 { 341 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 2, 4 }); 342 343 Assert.True(new[] { 1, 2, 2, 4 }.SequenceEqual(rocb)); 344 345 Assert.False(rocb.Remove(0)); 346 347 Assert.True(new[] { 1, 2, 2, 4 }.SequenceEqual(rocb)); 348 349 Assert.True(rocb.Remove(2)); 350 351 Assert.True(new[] { 1, 2, 4 }.SequenceEqual(rocb)); 352 353 Assert.True(rocb.Remove(1)); 354 355 Assert.True(new[] { 2, 4 }.SequenceEqual(rocb)); 356 357 Assert.True(rocb.Remove(4)); 358 359 Assert.True(new[] { 2 }.SequenceEqual(rocb)); 360 361 Assert.True(rocb.Remove(2)); 362 363 Assert.Equal(0, rocb.Count); 364 } 365 366 [Fact] ReadOnlyCollectionBuilder_IList_Remove()367 public void ReadOnlyCollectionBuilder_IList_Remove() 368 { 369 IList rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 2, 4 }); 370 371 Assert.True(new[] { 1, 2, 2, 4 }.SequenceEqual(rocb.Cast<int>())); 372 373 rocb.Remove(0); 374 rocb.Remove("bar"); 375 rocb.Remove(null); 376 377 Assert.True(new[] { 1, 2, 2, 4 }.SequenceEqual(rocb.Cast<int>())); 378 379 rocb.Remove(2); 380 381 Assert.True(new[] { 1, 2, 4 }.SequenceEqual(rocb.Cast<int>())); 382 383 rocb.Remove(1); 384 385 Assert.True(new[] { 2, 4 }.SequenceEqual(rocb.Cast<int>())); 386 387 rocb.Remove(4); 388 389 Assert.True(new[] { 2 }.SequenceEqual(rocb.Cast<int>())); 390 391 rocb.Remove(2); 392 393 Assert.Equal(0, rocb.Count); 394 } 395 396 [Fact] ReadOnlyCollectionBuilder_Indexer_Get()397 public void ReadOnlyCollectionBuilder_Indexer_Get() 398 { 399 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3, 4 }); 400 401 // CONSIDER: Throw ArgumentOutOfRangeException instead, see https://github.com/dotnet/corefx/issues/14059 402 Assert.Throws<IndexOutOfRangeException>(() => rocb[-1]); 403 AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => rocb[4]); 404 405 Assert.Equal(1, rocb[0]); 406 Assert.Equal(2, rocb[1]); 407 Assert.Equal(3, rocb[2]); 408 Assert.Equal(4, rocb[3]); 409 } 410 411 [Fact] ReadOnlyCollectionBuilder_Indexer_IList_Get()412 public void ReadOnlyCollectionBuilder_Indexer_IList_Get() 413 { 414 IList rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3, 4 }); 415 416 // CONSIDER: Throw ArgumentOutOfRangeException instead, see https://github.com/dotnet/corefx/issues/14059 417 Assert.Throws<IndexOutOfRangeException>(() => rocb[-1]); 418 AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => rocb[4]); 419 420 Assert.Equal(1, rocb[0]); 421 Assert.Equal(2, rocb[1]); 422 Assert.Equal(3, rocb[2]); 423 Assert.Equal(4, rocb[3]); 424 } 425 426 [Fact] ReadOnlyCollectionBuilder_Indexer_Set()427 public void ReadOnlyCollectionBuilder_Indexer_Set() 428 { 429 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3, 4 }); 430 431 // CONSIDER: Throw ArgumentOutOfRangeException instead, see https://github.com/dotnet/corefx/issues/14059 432 Assert.Throws<IndexOutOfRangeException>(() => rocb[-1] = -1); 433 AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => rocb[4] = -1); 434 435 rocb[0] = -1; 436 Assert.Equal(-1, rocb[0]); 437 438 rocb[1] = -2; 439 Assert.Equal(-2, rocb[1]); 440 441 rocb[2] = -3; 442 Assert.Equal(-3, rocb[2]); 443 444 rocb[3] = -4; 445 Assert.Equal(-4, rocb[3]); 446 } 447 448 [Fact] ReadOnlyCollectionBuilder_Indexer_IList_Set()449 public void ReadOnlyCollectionBuilder_Indexer_IList_Set() 450 { 451 IList rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3, 4 }); 452 453 // CONSIDER: Throw ArgumentOutOfRangeException instead, see https://github.com/dotnet/corefx/issues/14059 454 Assert.Throws<IndexOutOfRangeException>(() => rocb[-1] = -1); 455 AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => rocb[4] = -1); 456 457 AssertExtensions.Throws<ArgumentException>("value", () => rocb[0] = "bar"); 458 AssertExtensions.Throws<ArgumentException>("value", () => rocb[0] = null); 459 460 rocb[0] = -1; 461 Assert.Equal(-1, rocb[0]); 462 463 rocb[1] = -2; 464 Assert.Equal(-2, rocb[1]); 465 466 rocb[2] = -3; 467 Assert.Equal(-3, rocb[2]); 468 469 rocb[3] = -4; 470 Assert.Equal(-4, rocb[3]); 471 } 472 473 [Fact] ReadOnlyCollectionBuilder_Add()474 public void ReadOnlyCollectionBuilder_Add() 475 { 476 var rocb = new ReadOnlyCollectionBuilder<int>(); 477 478 for (int i = 1; i <= 10; i++) 479 { 480 rocb.Add(i); 481 482 Assert.True(Enumerable.Range(1, i).SequenceEqual(rocb)); 483 } 484 } 485 486 [Fact] ReadOnlyCollectionBuilder_IList_Add()487 public void ReadOnlyCollectionBuilder_IList_Add() 488 { 489 IList rocb = new ReadOnlyCollectionBuilder<int>(); 490 491 for (int i = 1; i <= 10; i++) 492 { 493 rocb.Add(i); 494 495 Assert.True(Enumerable.Range(1, i).SequenceEqual(rocb.Cast<int>())); 496 } 497 498 AssertExtensions.Throws<ArgumentException>("value", () => rocb.Add(null)); 499 AssertExtensions.Throws<ArgumentException>("value", () => rocb.Add("foo")); 500 } 501 502 [Fact] ReadOnlyCollectionBuilder_Clear1()503 public void ReadOnlyCollectionBuilder_Clear1() 504 { 505 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 }); 506 507 rocb.Clear(); 508 509 Assert.Equal(0, rocb.Count); 510 } 511 512 [Fact] ReadOnlyCollectionBuilder_Clear2()513 public void ReadOnlyCollectionBuilder_Clear2() 514 { 515 var rocb = new ReadOnlyCollectionBuilder<int>(); 516 517 rocb.Clear(); 518 519 Assert.Equal(0, rocb.Count); 520 } 521 522 [Fact] ReadOnlyCollectionBuilder_Contains1()523 public void ReadOnlyCollectionBuilder_Contains1() 524 { 525 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 2, 3 }); 526 527 Assert.True(rocb.Contains(1)); 528 Assert.True(rocb.Contains(2)); 529 Assert.True(rocb.Contains(3)); 530 531 Assert.False(rocb.Contains(-1)); 532 } 533 534 [Fact] ReadOnlyCollectionBuilder_Contains2()535 public void ReadOnlyCollectionBuilder_Contains2() 536 { 537 var rocb = new ReadOnlyCollectionBuilder<string>(new[] { "bar", "foo", "qux" }); 538 539 Assert.True(rocb.Contains("bar")); 540 Assert.True(rocb.Contains("foo")); 541 Assert.True(rocb.Contains("qux")); 542 543 Assert.False(rocb.Contains(null)); 544 Assert.False(rocb.Contains("baz")); 545 } 546 547 [Fact] ReadOnlyCollectionBuilder_Contains3()548 public void ReadOnlyCollectionBuilder_Contains3() 549 { 550 var rocb = new ReadOnlyCollectionBuilder<string>(new[] { "bar", "foo", "qux", null }); 551 552 Assert.True(rocb.Contains("bar")); 553 Assert.True(rocb.Contains("foo")); 554 Assert.True(rocb.Contains("qux")); 555 Assert.True(rocb.Contains(null)); 556 557 Assert.False(rocb.Contains("baz")); 558 } 559 560 [Fact] ReadOnlyCollectionBuilder_IList_Contains1()561 public void ReadOnlyCollectionBuilder_IList_Contains1() 562 { 563 IList rocb = new ReadOnlyCollectionBuilder<string>(new[] { "bar", "foo", "qux", null }); 564 565 Assert.True(rocb.Contains("bar")); 566 Assert.True(rocb.Contains("foo")); 567 Assert.True(rocb.Contains("qux")); 568 Assert.True(rocb.Contains(null)); 569 570 Assert.False(rocb.Contains("baz")); 571 Assert.False(rocb.Contains(42)); 572 } 573 574 [Fact] ReadOnlyCollectionBuilder_IList_Contains2()575 public void ReadOnlyCollectionBuilder_IList_Contains2() 576 { 577 IList rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 }); 578 579 Assert.True(rocb.Contains(1)); 580 Assert.True(rocb.Contains(2)); 581 Assert.True(rocb.Contains(3)); 582 583 Assert.False(rocb.Contains("baz")); 584 Assert.False(rocb.Contains(0)); 585 Assert.False(rocb.Contains(null)); 586 } 587 588 [Fact] ReadOnlyCollectionBuilder_Reverse()589 public void ReadOnlyCollectionBuilder_Reverse() 590 { 591 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 }); 592 593 rocb.Reverse(); 594 595 Assert.True(new[] { 3, 2, 1 }.SequenceEqual(rocb)); 596 } 597 598 [Fact] ReadOnlyCollectionBuilder_Reverse_Range_ArgumentChecking()599 public void ReadOnlyCollectionBuilder_Reverse_Range_ArgumentChecking() 600 { 601 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 }); 602 603 AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => rocb.Reverse(-1, 1)); 604 AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => rocb.Reverse(1, -1)); 605 606 // CONSIDER: Throw ArgumentException just like List<T> does, see https://github.com/dotnet/corefx/issues/14059 607 // AssertExtensions.Throws<ArgumentException>(null, () => rocb.Reverse(3, 1)); 608 // AssertExtensions.Throws<ArgumentException>(null, () => rocb.Reverse(1, 3)); 609 // AssertExtensions.Throws<ArgumentException>(null, () => rocb.Reverse(2, 2)); 610 // AssertExtensions.Throws<ArgumentException>(null, () => rocb.Reverse(3, 1)); 611 } 612 613 [Fact] ReadOnlyCollectionBuilder_Reverse_Range()614 public void ReadOnlyCollectionBuilder_Reverse_Range() 615 { 616 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3, 4, 5 }); 617 618 rocb.Reverse(1, 3); 619 620 Assert.True(new[] { 1, 4, 3, 2, 5 }.SequenceEqual(rocb)); 621 } 622 623 [Theory] 624 [MemberData(nameof(Lengths))] ReadOnlyCollectionBuilder_ToArray(int length)625 public void ReadOnlyCollectionBuilder_ToArray(int length) 626 { 627 var rocb = new ReadOnlyCollectionBuilder<int>(); 628 629 for (int i = 0; i < length; i++) 630 { 631 rocb.Add(i); 632 } 633 634 int[] array = rocb.ToArray(); 635 636 Assert.True(Enumerable.Range(0, length).SequenceEqual(array)); 637 } 638 639 [Theory] 640 [MemberData(nameof(Lengths))] ReadOnlyCollectionBuilder_ToReadOnlyCollection(int length)641 public void ReadOnlyCollectionBuilder_ToReadOnlyCollection(int length) 642 { 643 var rocb = new ReadOnlyCollectionBuilder<int>(); 644 645 for (int i = 0; i < length; i++) 646 { 647 rocb.Add(i); 648 } 649 650 ReadOnlyCollection<int> collection = rocb.ToReadOnlyCollection(); 651 652 Assert.Equal(length, collection.Count); 653 654 Assert.True(Enumerable.Range(0, length).SequenceEqual(collection)); 655 656 AssertEmpty(rocb); 657 } 658 659 [Theory] 660 [MemberData(nameof(Lengths))] ReadOnlyCollectionBuilder_GetEnumerator(int length)661 public void ReadOnlyCollectionBuilder_GetEnumerator(int length) 662 { 663 var rocb = new ReadOnlyCollectionBuilder<int>(); 664 665 for (int i = 0; i < length; i++) 666 { 667 rocb.Add(i); 668 } 669 670 for (int j = 0; j < 2; j++) 671 { 672 IEnumerator<int> enumerator = rocb.GetEnumerator(); 673 674 // NB: Current property on generic enumerator doesn't throw; this is consistent with List<T>. 675 676 for (int i = 0; i < length; i++) 677 { 678 Assert.True(enumerator.MoveNext()); 679 Assert.Equal(i, enumerator.Current); 680 Assert.Equal(i, ((IEnumerator)enumerator).Current); 681 682 enumerator.Dispose(); // NB: Similar to List<T>, calling Dispose does not have an effect here 683 } 684 685 Assert.False(enumerator.MoveNext()); 686 Assert.False(enumerator.MoveNext()); 687 688 // NB: Current property on generic enumerator doesn't throw; this is consistent with List<T>. 689 690 enumerator.Reset(); 691 } 692 } 693 694 [Theory] 695 [MemberData(nameof(Lengths))] ReadOnlyCollectionBuilder_IEnumerable_GetEnumerator(int length)696 public void ReadOnlyCollectionBuilder_IEnumerable_GetEnumerator(int length) 697 { 698 var rocb = new ReadOnlyCollectionBuilder<int>(); 699 700 for (int i = 0; i < length; i++) 701 { 702 rocb.Add(i); 703 } 704 705 for (int j = 0; j < 2; j++) 706 { 707 IEnumerator enumerator = ((IEnumerable)rocb).GetEnumerator(); 708 709 Assert.Throws<InvalidOperationException>(() => enumerator.Current); 710 711 for (int i = 0; i < length; i++) 712 { 713 Assert.True(enumerator.MoveNext()); 714 Assert.Equal(i, enumerator.Current); 715 Assert.Equal(i, ((IEnumerator)enumerator).Current); 716 717 ((IDisposable)enumerator).Dispose(); // NB: Similar to List<T>, calling Dispose does not have an effect here 718 } 719 720 Assert.False(enumerator.MoveNext()); 721 Assert.False(enumerator.MoveNext()); 722 723 Assert.Throws<InvalidOperationException>(() => enumerator.Current); 724 725 enumerator.Reset(); 726 } 727 } 728 729 [Theory] 730 [MemberData(nameof(Versioning))] ReadOnlyCollectionBuilder_IEnumeratorOfT_Versioning_MoveNext(int index, Action<ReadOnlyCollectionBuilder<int>> edit)731 public void ReadOnlyCollectionBuilder_IEnumeratorOfT_Versioning_MoveNext(int index, Action<ReadOnlyCollectionBuilder<int>> edit) 732 { 733 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 }); 734 735 IEnumerator<int> enumerator = rocb.GetEnumerator(); 736 737 Assert.True(enumerator.MoveNext()); 738 739 edit(rocb); 740 741 Assert.Throws<InvalidOperationException>(() => enumerator.MoveNext()); 742 } 743 744 [Theory] 745 [MemberData(nameof(Versioning))] ReadOnlyCollectionBuilder_IEnumeratorOfT_Versioning_Reset(int index, Action<ReadOnlyCollectionBuilder<int>> edit)746 public void ReadOnlyCollectionBuilder_IEnumeratorOfT_Versioning_Reset(int index, Action<ReadOnlyCollectionBuilder<int>> edit) 747 { 748 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 }); 749 750 IEnumerator<int> enumerator = rocb.GetEnumerator(); 751 752 Assert.True(enumerator.MoveNext()); 753 754 edit(rocb); 755 756 Assert.Throws<InvalidOperationException>(() => enumerator.Reset()); 757 } 758 759 [Theory] 760 [MemberData(nameof(Versioning))] ReadOnlyCollectionBuilder_IEnumerator_Versioning_MoveNext(int index, Action<ReadOnlyCollectionBuilder<int>> edit)761 public void ReadOnlyCollectionBuilder_IEnumerator_Versioning_MoveNext(int index, Action<ReadOnlyCollectionBuilder<int>> edit) 762 { 763 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 }); 764 765 IEnumerator enumerator = ((IEnumerable)rocb).GetEnumerator(); 766 767 Assert.True(enumerator.MoveNext()); 768 769 edit(rocb); 770 771 Assert.Throws<InvalidOperationException>(() => enumerator.MoveNext()); 772 } 773 774 [Theory] 775 [MemberData(nameof(Versioning))] ReadOnlyCollectionBuilder_IEnumerator_Versioning_Reset(int index, Action<ReadOnlyCollectionBuilder<int>> edit)776 public void ReadOnlyCollectionBuilder_IEnumerator_Versioning_Reset(int index, Action<ReadOnlyCollectionBuilder<int>> edit) 777 { 778 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 }); 779 780 IEnumerator enumerator = ((IEnumerable)rocb).GetEnumerator(); 781 782 Assert.True(enumerator.MoveNext()); 783 784 edit(rocb); 785 786 Assert.Throws<InvalidOperationException>(() => enumerator.Reset()); 787 } 788 789 [Fact] ReadOnlyCollectionBuilder_CopyTo_ArgumentChecking()790 public void ReadOnlyCollectionBuilder_CopyTo_ArgumentChecking() 791 { 792 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 }); 793 794 Assert.Throws<ArgumentNullException>(() => rocb.CopyTo(null, 0)); 795 Assert.Throws<ArgumentOutOfRangeException>(() => rocb.CopyTo(new int[3], -1)); 796 AssertExtensions.Throws<ArgumentException>("destinationArray", () => rocb.CopyTo(new int[3], 3)); // NB: Consistent with List<T> behavior 797 } 798 799 [Fact] ReadOnlyCollectionBuilder_CopyTo1()800 public void ReadOnlyCollectionBuilder_CopyTo1() 801 { 802 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 }); 803 804 var array = new int[3]; 805 806 rocb.CopyTo(array, 0); 807 808 Assert.True(new[] { 1, 2, 3 }.SequenceEqual(array)); 809 } 810 811 [Fact] ReadOnlyCollectionBuilder_CopyTo2()812 public void ReadOnlyCollectionBuilder_CopyTo2() 813 { 814 var rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 }); 815 816 var array = new int[5] { 1, 2, 3, 4, 5 }; 817 818 rocb.CopyTo(array, 1); 819 820 Assert.True(new[] { 1, 1, 2, 3, 5 }.SequenceEqual(array)); 821 } 822 823 [Fact] ReadOnlyCollectionBuilder_ICollection_CopyTo_ArgumentChecking()824 public void ReadOnlyCollectionBuilder_ICollection_CopyTo_ArgumentChecking() 825 { 826 ICollection rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 }); 827 828 Assert.Throws<ArgumentNullException>(() => rocb.CopyTo(null, 0)); 829 Assert.Throws<ArgumentOutOfRangeException>(() => rocb.CopyTo(new int[3], -1)); 830 AssertExtensions.Throws<ArgumentException>("destinationArray", () => rocb.CopyTo(new int[3], 3)); // NB: Consistent with List<T> behavior 831 AssertExtensions.Throws<ArgumentException>(null, () => rocb.CopyTo(new int[3, 3], 0)); 832 833 // CONSIDER: Throw ArgumentException instead to be consistent with List<T>, see https://github.com/dotnet/corefx/issues/14059 834 Assert.Throws<ArrayTypeMismatchException>(() => rocb.CopyTo(new string[3], 0)); 835 } 836 837 [Fact] ReadOnlyCollectionBuilder_ICollection_CopyTo1()838 public void ReadOnlyCollectionBuilder_ICollection_CopyTo1() 839 { 840 ICollection rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 }); 841 842 var array = new int[3]; 843 844 rocb.CopyTo(array, 0); 845 846 Assert.True(new[] { 1, 2, 3 }.SequenceEqual(array)); 847 } 848 849 [Fact] ReadOnlyCollectionBuilder_ICollection_CopyTo2()850 public void ReadOnlyCollectionBuilder_ICollection_CopyTo2() 851 { 852 ICollection rocb = new ReadOnlyCollectionBuilder<int>(new[] { 1, 2, 3 }); 853 854 var array = new int[5] { 1, 2, 3, 4, 5 }; 855 856 rocb.CopyTo(array, 1); 857 858 Assert.True(new[] { 1, 1, 2, 3, 5 }.SequenceEqual(array)); 859 } 860 AssertEmpty(ReadOnlyCollectionBuilder<T> rocb)861 private static void AssertEmpty<T>(ReadOnlyCollectionBuilder<T> rocb) 862 { 863 Assert.Equal(0, rocb.Count); 864 865 Assert.False(rocb.Contains(default(T))); 866 Assert.False(rocb.Remove(default(T))); 867 Assert.InRange(rocb.IndexOf(default(T)), int.MinValue, -1); 868 869 IEnumerator<T> e = rocb.GetEnumerator(); 870 Assert.False(e.MoveNext()); 871 } 872 InitialCollections()873 private static IEnumerable<object[]> InitialCollections() => 874 new IEnumerable<int>[] 875 { 876 new int[0], 877 new int[] { 1 }, 878 new int[] { 1, 2 }, 879 new int[] { 1, 2, 3 }, 880 new int[] { 1, 2, 3, 4 }, 881 new int[] { 1, 2, 3, 4, 5 }, 882 883 new List<int>(), 884 new List<int>() { 1 }, 885 new List<int>() { 1, 2 }, 886 new List<int>() { 1, 2, 3 }, 887 new List<int>() { 1, 2, 3, 4 }, 888 new List<int>() { 1, 2, 3, 4, 5 }, 889 890 Enumerable.Empty<int>(), 891 Enumerable.Range(1, 1), 892 Enumerable.Range(1, 2), 893 Enumerable.Range(1, 3), 894 Enumerable.Range(1, 4), 895 Enumerable.Range(1, 5), 896 }.Select(x => new object[] { x }); 897 Lengths()898 private static IEnumerable<object[]> Lengths() => Enumerable.Range(0, 10).Select(i => new object[] { i }); 899 Versioning()900 private static IEnumerable<object[]> Versioning() => 901 new Action<ReadOnlyCollectionBuilder<int>>[] 902 { 903 e => e.Add(1), 904 e => ((IList)e).Add(1), 905 e => e[0] = 1, 906 e => ((IList)e)[0] = 1, 907 e => e.Insert(0, 1), 908 e => ((IList)e).Insert(0, 1), 909 e => e.Remove(1), 910 e => ((IList)e).Remove(1), 911 e => e.RemoveAt(0), 912 e => e.Reverse(), 913 }.Select((x, i) => new object[] { i, x }); 914 } 915 } 916