Initial commit
This commit is contained in:
commit
593d8ebfea
30 changed files with 2206 additions and 0 deletions
153
BucketChain.Test/ChainTests.cs
Normal file
153
BucketChain.Test/ChainTests.cs
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
using FluentAssertions;
|
||||
using Xunit;
|
||||
|
||||
namespace BucketChain.Test;
|
||||
|
||||
public sealed class ChainTests
|
||||
{
|
||||
private const double InitialFireSize = 10D;
|
||||
private const double FireGrowthRate = 0.25D;
|
||||
private const double WellSize = 20D;
|
||||
private const double WellRefillRate = 0.5D;
|
||||
private const double BucketSize = 1.5D;
|
||||
|
||||
[Fact]
|
||||
public void Construction()
|
||||
{
|
||||
new Chain(10, 5, BucketSize, new Well(WellSize, WellRefillRate),
|
||||
new Fire(InitialFireSize, FireGrowthRate), new Person())
|
||||
.Should().NotBeNull("only sets private fields, not much to check here");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Operate_Minimal()
|
||||
{
|
||||
const double FireSize = 3D;
|
||||
var (chain, fire, well, first) = CreateMinimalChain(2, 2,
|
||||
2, FireSize);
|
||||
|
||||
// step 1
|
||||
// new bucket handed to first person who filled it, then moved to second person
|
||||
chain.Operate(1, out var error)
|
||||
.Should().BeFalse("fire still burning");
|
||||
error.Should().BeFalse("no problem so far");
|
||||
first.HasBucket.Should().BeFalse("moved to second person already");
|
||||
first.RightNeighbor?.HasBucket.Should().BeTrue("has the new bucket");
|
||||
well.LitersRemaining.Should().BeApproximately(WellSize - BucketSize,
|
||||
double.Epsilon, "bucket has been filled");
|
||||
fire.Extinguished.Should().BeFalse("still burning");
|
||||
fire.FireSize.Should().BeApproximately(FireSize + FireGrowthRate - BucketSize,
|
||||
double.Epsilon, "fire grew, then got hit by the water in the bucket");
|
||||
|
||||
var wellSize = well.LitersRemaining;
|
||||
var fireSize = fire.FireSize;
|
||||
// step 2
|
||||
// new bucket handed to first person who filled it, then moved to the second person
|
||||
// empty bucket from previous step handed from second person to first
|
||||
chain.Operate(2, out error)
|
||||
.Should().BeFalse("fire still burning");
|
||||
error.Should().BeFalse("no problem so far");
|
||||
first.HasBucket.Should().BeTrue("there are now two buckets, has the one from step 1");
|
||||
first.RightNeighbor?.HasBucket.Should().BeTrue("has the new bucket");
|
||||
well.LitersRemaining.Should().BeApproximately(wellSize + WellRefillRate - BucketSize,
|
||||
double.Epsilon, "well refilled, then bucket has been filled");
|
||||
fire.Extinguished.Should().BeFalse("still burning");
|
||||
fire.FireSize.Should().BeApproximately(fireSize + FireGrowthRate - BucketSize,
|
||||
double.Epsilon, "fire grew, then got hit by the water in the bucket");
|
||||
|
||||
wellSize = well.LitersRemaining;
|
||||
// step 3
|
||||
// no new buckets added, existing two continue circulating
|
||||
chain.Operate(3, out error)
|
||||
.Should().BeTrue("fire extinguished");
|
||||
error.Should().BeFalse("no problem so far");
|
||||
well.LitersRemaining.Should().BeApproximately(wellSize + WellRefillRate - BucketSize,
|
||||
double.Epsilon, "well refilled, then bucket has been filled");
|
||||
fire.Extinguished.Should().BeTrue();
|
||||
fire.FireSize.Should().BeApproximately(0D,
|
||||
double.Epsilon, "fire extinguished, but size cannot become negative");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Operate_NotLongEnough()
|
||||
{
|
||||
const int Steps = 100;
|
||||
var (chain, fire, _, _) = CreateMinimalChain(4, 3, 2);
|
||||
|
||||
for (var i = 0; i < Steps; i++)
|
||||
{
|
||||
chain.Operate(i + 1, out var error)
|
||||
.Should().BeFalse("fire keeps burning");
|
||||
error.Should().BeFalse("no error, chain is simply not long enough");
|
||||
}
|
||||
|
||||
fire.Extinguished.Should().BeFalse();
|
||||
fire.FireSize.Should().BeApproximately(InitialFireSize + FireGrowthRate * Steps,
|
||||
2E-14, "fire keeps growing");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Operate_Initially_NotLongEnough()
|
||||
{
|
||||
const int FirstSteps = 5;
|
||||
var (chain, fire, _, firstPerson) = CreateMinimalChain(4, 2, 2);
|
||||
|
||||
var initialSize = fire.FireSize;
|
||||
for (var i = 0; i < FirstSteps; i++)
|
||||
{
|
||||
chain.Operate(i + 1, out var error)
|
||||
.Should().BeFalse("fire keeps burning");
|
||||
error.Should().BeFalse("no error, chain is simply not long enough");
|
||||
}
|
||||
fire.FireSize.Should().BeGreaterThan(initialSize, "fire grew");
|
||||
|
||||
// two additional people, but no more buckets, stays at 2
|
||||
new Person().JoinChain(firstPerson, true);
|
||||
new Person().JoinChain(firstPerson, true);
|
||||
|
||||
var s = FirstSteps;
|
||||
while (!chain.Operate(++s, out var error))
|
||||
{
|
||||
fire.Extinguished.Should().BeFalse();
|
||||
error.Should().BeFalse();
|
||||
}
|
||||
|
||||
fire.FireSize.Should().BeApproximately(0D, double.Epsilon, "fire extinguished");
|
||||
s.Should().Be(49);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StringRepresentation()
|
||||
{
|
||||
var (chain, fire, well, firstPerson) = CreateMinimalChain(4, 2, 1);
|
||||
chain.Operate(1, out _);
|
||||
|
||||
chain.ToString()
|
||||
.Should().Be($"{well} | {firstPerson} | {firstPerson.RightNeighbor} | ❔ | ❔ | {fire}");
|
||||
}
|
||||
|
||||
private static (Chain Chain, Fire Fire, Well Well, Person FirstPerson) CreateMinimalChain(int requiredPeople,
|
||||
int peopleCount, int buckets, double? initialFireSize = null)
|
||||
{
|
||||
var fire = new Fire(initialFireSize ?? InitialFireSize, FireGrowthRate);
|
||||
var well = new Well(WellSize, WellRefillRate);
|
||||
var firstPerson = CreatePeople();
|
||||
var chain = new Chain(requiredPeople, buckets, BucketSize, well, fire, firstPerson);
|
||||
|
||||
return (chain, fire, well, firstPerson);
|
||||
|
||||
Person CreatePeople()
|
||||
{
|
||||
var first = new Person();
|
||||
var prev = first;
|
||||
for (var i = 1; i < peopleCount; i++)
|
||||
{
|
||||
var newPerson = new Person();
|
||||
newPerson.JoinChain(prev, true);
|
||||
prev = newPerson;
|
||||
}
|
||||
|
||||
return first;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue