using FluentAssertions; using Xunit; namespace BucketChain.Test; public sealed class WellTests { private const double MaxCapacity = 20D; private const double RefillRate = 0.75D; private const double BucketSize = 2.3D; [Fact] public void Construction() { var well = new Well(MaxCapacity, default); well.LitersRemaining.Should().Be(MaxCapacity, "initially a well is filled completely"); } [Fact] public void FillBucket_Simple() { var well = new Well(MaxCapacity, default); var bucket = new Bucket(BucketSize); bucket.IsEmpty.Should().BeTrue(); well.FillBucket(bucket); bucket.IsEmpty.Should().BeFalse(); well.LitersRemaining.Should().BeApproximately(MaxCapacity - BucketSize, double.Epsilon, "bucket capacity drawn from the well"); } [Fact] public void FillBucket_Multiple() { const int Times = 5; var well = new Well(MaxCapacity, default); for (var i = 0; i < Times; i++) { well.FillBucket(new(BucketSize)); } well.LitersRemaining.Should().BeApproximately(MaxCapacity - BucketSize * Times, 2E-14, "bucket capacity drawn from the well several times"); } [Fact] public void FillBucket_Empty() { var well = new Well(MaxCapacity, default); var bucket = new Bucket(BucketSize); well.FillBucket(new(MaxCapacity)); well.FillBucket(bucket); bucket.IsEmpty.Should().BeTrue("nothing left in the well"); well.LitersRemaining.Should().BeApproximately(0, double.Epsilon, "well is empty"); } [Fact] public void FillBucket_AlmostEmpty() { var well = new Well(MaxCapacity, default); var bucket = new Bucket(BucketSize); well.FillBucket(new(MaxCapacity - BucketSize / 2)); well.FillBucket(bucket); bucket.IsEmpty.Should().BeFalse("half full"); well.LitersRemaining.Should().BeApproximately(0, double.Epsilon, "well is empty"); } [Fact] public void Refill_Simple() { var well = new Well(MaxCapacity, RefillRate); well.FillBucket(new(MaxCapacity / 2)); well.Refill(); well.LitersRemaining.Should().BeApproximately(MaxCapacity / 2 + RefillRate, 2E-14, "well has been refilled by rate"); } [Fact] public void Refill_Multiple() { const int Times = 8; var well = new Well(MaxCapacity, RefillRate); well.FillBucket(new(MaxCapacity / 2)); for (var i = 0; i < Times; i++) { well.Refill(); } well.LitersRemaining.Should().BeApproximately(MaxCapacity / 2 + RefillRate * Times, 2E-14, "well has been refilled several times, but is not yet full"); } [Fact] public void Refill_AlreadyFull() { var well = new Well(MaxCapacity, RefillRate); well.Refill(); well.LitersRemaining.Should().Be(MaxCapacity, "max capacity cannot be exceeded"); } [Fact] public void StringRepresentation() { var well = new Well(MaxCapacity, RefillRate); well.FillBucket(new(BucketSize * 2)); well.Refill(); well.ToString() .Should().Be("💧 16/20"); } }