namespace FlexArray.Test; public class FlexArrayStringTests { // Constructor tests [Fact] public void Construction_NoSize() { var array = new FlexArrayString(); array.Should().NotBeNull(); array.Count.Should().Be(0, "no items added yet"); array.Capacity.Should().Be(FlexArrayString.DefaultStartSize, "default capacity"); } [Theory] [InlineData(0)] [InlineData(4)] [InlineData(20)] [InlineData(100_000)] public void Construction_WithSize(int size) { var array = new FlexArrayString(size); array.Should().NotBeNull(); array.Count.Should().Be(0, "no items added yet"); array.Capacity.Should().Be(size, "initial capacity set to specified size"); } [Fact] public void Construction_WithInvalidSize() { var array = new FlexArrayString(-5); array.Should().NotBeNull(); array.Count.Should().Be(0); array.Capacity.Should().Be(0, "negative size provided => set to 0"); } // Add tests [Fact] public void AddItem_Single() { var array = new FlexArrayString(); array.Add("Hello"); array.Count.Should().Be(1, "one item added"); array.Capacity.Should().Be(FlexArrayString.DefaultStartSize, "capacity unchanged"); } [Fact] public void AddItem_Multiple_NoGrowth() { var array = new FlexArrayString(); array.Add("Hello"); array.Add("World"); array.Add("!"); array.Count.Should().Be(3, "three items added"); array.Capacity.Should().Be(FlexArrayString.DefaultStartSize, "no growth required yet"); } [Fact] public void AddItem_Multiple_Growth() { var array = new FlexArrayString(); void AddItems(int count) { for (var i = 0; i < count; i++) { // random string array.Add(Guid.NewGuid().ToString()); } } AddItems(FlexArrayString.DefaultStartSize); array.Capacity.Should().Be(FlexArrayString.DefaultStartSize); AddItems(2); array.Capacity.Should().BeGreaterThan(FlexArrayString.DefaultStartSize, "capacity exceeded, had to grow"); array.Count.Should().Be(FlexArrayString.DefaultStartSize + 2); } // Contains tests [Fact] public void Contains_Success() { var array = new FlexArrayString(); array.Add("Goodbye"); array.Add("World"); array.Add("!"); array.Add("bye..."); array.Contains("!") .Should().BeTrue(); } [Fact] public void Contains_Success_AfterGrowth() { var array = new FlexArrayString(); for (var i = 0; i <= FlexArrayString.DefaultStartSize; i++) { array.Add(i.ToString()); } array.Contains(array[FlexArrayString.DefaultStartSize - 1]) .Should().BeTrue(); } [Fact] public void Contains_Empty() { var array = new FlexArrayString(); array.Contains("Hi!") .Should().BeFalse("collection is empty"); } [Fact] public void Contains_NotFound() { var array = new FlexArrayString(); array.Add("Hello"); array.Add("World"); array.Contains("!") .Should().BeFalse("not contained in list"); } // Indexer tests [Fact] public void Indexer_Simple() { var array = new FlexArrayString(); array.Add("Goodbye World!"); array[0].Should().Be("Goodbye World!"); } [Fact] public void Indexer_Multiple() { var array = new FlexArrayString(); for (var i = 0; i < 100; i++) { array.Add((i+1).ToString()); } array[20].Should().Be("21"); array[88].Should().Be("89"); } [Theory] [InlineData(-1, "negative index")] [InlineData(2, "index too high")] [InlineData(10, "index too high")] public void Indexer_InvalidIndex(int index, string reason) { var array = new FlexArrayString(); array.Add("Hello"); array[index].Should().Be(String.Empty, reason); } [Fact] public void Iterate() { var array = new FlexArrayString(); for (var i = 0; i < 10; i++) { array.Add(i.ToString()); } for (var i = 0; i < 10; i++) { array[i].Should().Be(i.ToString()); } } // Remove tests [Fact] public void Remove_ByIndex_Simple() { var array = new FlexArrayString(); array.Add("Hello"); array.Count.Should().Be(1); array.RemoveAt(0).Should().BeTrue("index exists"); array.Count.Should().Be(0, "count has to be reduced"); } [Fact] public void Remove_ByIndex_Shifting() { var array = new FlexArrayString(); array.Add("Goodbye"); array.Add("World"); array.Add("!"); array.Count.Should().Be(3); array.RemoveAt(1).Should().BeTrue(); array.Count.Should().Be(2); array[1].Should().Be("!", "items to the right have to be shifted left after removal"); array.RemoveAt(2) .Should().BeFalse("not a valid index any longer, despite a value still being there"); } [Fact] public void Remove_ByIndex_FromEnd() { var array = new FlexArrayString(); array.Add("Hello"); array.Add("World"); array.Add("!"); array.Count.Should().Be(3); array.RemoveAt(2).Should().BeTrue(); array.Count.Should().Be(2); array[1].Should().Be("World"); } [Fact] public void Remove_ByIndex_Invalid() { var array = new FlexArrayString(); array.Add("This is a test!"); array.RemoveAt(1) .Should().BeFalse("the array is big enough for this index, but no value has been set there"); array.Count.Should().Be(1, "unchanged"); array.RemoveAt(-1) .Should().BeFalse("negative index doesn't make any sense"); } [Fact] public void Remove_Single_OneOccurrence() { var array = new FlexArrayString(); array.Add("Hello"); array.Add("corrupted"); array.Add("World!"); array.Remove("corrupted", true) .Should().BeTrue("element was found"); array.Count.Should().Be(2, "element was removed"); } [Fact] public void Remove_Single_OnlyOccurrence() { var array = new FlexArrayString(); array.Add("Hello"); array.Remove("Hello", true) .Should().BeTrue("element was found"); array.Count.Should().Be(0, "element was removed"); } [Fact] public void Remove_Single_MultipleOccurrence() { var array = new FlexArrayString(); array.Add("Ever"); array.Add("used"); array.Add("kubernetes?"); array.Remove("kubernetes?", true) .Should().BeTrue("element was found"); array.Count.Should().Be(2, "only one element was removed"); } [Fact] public void Remove_Single_NotFound() { var array = new FlexArrayString(); array.Add("1"); array.Add("2"); array.Add("3"); array.Remove("4", true) .Should().BeFalse("element was not found"); array.Count.Should().Be(3, "unchanged"); } [Fact] public void Remove_Multiple_OneOccurrence() { var array = new FlexArrayString(); array.Add("1"); array.Add("2"); array.Add("3"); array.Remove("2", false) .Should().BeTrue("element was found"); array.Count.Should().Be(2, "only one element was removed"); } [Fact] public void Remove_Multiple_MultipleOccurrence() { var array = new FlexArrayString(); array.Add("1"); array.Add("2"); array.Add("2"); array.Add("3"); array.Add("2"); array.Add("4"); array.Add("2"); array.Remove("2", false) .Should().BeTrue("elements were found"); array.Count.Should().Be(3, "four elements were removed"); } [Fact] public void Remove_Multiple_OnlyOccurrence() { var array = new FlexArrayString(); array.Add("1"); array.Add("1"); array.Add("1"); array.Remove("1", false) .Should().BeTrue("elements were found"); array.Count.Should().Be(0, "all elements were removed"); } [Fact] public void Remove_Multiple_NoOccurrence() { var array = new FlexArrayString(); array.Add("1"); array.Add("2"); array.Add("3"); array.Remove("4", false) .Should().BeFalse("element was not found"); array.Count.Should().Be(3, "unchanged"); } }