diff --git a/DigiTally/ReadBallots.cs b/DigiTally/ReadBallots.cs index eb0c725..a42df77 100644 --- a/DigiTally/ReadBallots.cs +++ b/DigiTally/ReadBallots.cs @@ -2,17 +2,19 @@ // This software is licensed under the GNU General Public License version 3 // (https://opensource.org/licenses/GPL-3.0) +using System; using System.Collections.Generic; using System.IO; using System.Text; using DigitaleBriefwahl.Model; +using SIL.Providers; namespace DigitaleBriefwahl.Tally { public class ReadBallots { - private Configuration _configuration; - private Dictionary> _results; + private readonly Configuration _configuration; + private readonly Dictionary> _results; public ReadBallots(string configFileName) { @@ -78,6 +80,9 @@ public string GetResultString() strBuilder.AppendLine(new string('-', election.Key.Name.Length)); strBuilder.AppendLine(election.Key.GetResultString(election.Value)); } + + strBuilder.AppendLine($"(DigiTally version {GitVersionInformation.SemVer}; " + + $"report executed {DateTimeProvider.Current.Now:yyyy-MM-dd HH:mm})"); return strBuilder.ToString(); } } diff --git a/DigiTallyTests/AcceptanceTests.cs b/DigiTallyTests/AcceptanceTests.cs index 00934b1..f70686b 100644 --- a/DigiTallyTests/AcceptanceTests.cs +++ b/DigiTallyTests/AcceptanceTests.cs @@ -2,10 +2,13 @@ // This software is licensed under the GNU General Public License version 3 // (https://opensource.org/licenses/GPL-3.0) +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using NUnit.Framework; +using SIL.Providers; +using SIL.TestUtilities.Providers; namespace DigitaleBriefwahl.Tally.Tests { @@ -58,6 +61,7 @@ public void Teardown() [Test] public void EndToEnd() { + // Setup var ballotFileName1 = Path.Combine(_ballotDirectoryName, Path.GetRandomFileName()); File.WriteAllText(ballotFileName1, "The election\r\n" + "============\r\n" + @@ -127,9 +131,14 @@ public void EndToEnd() "\r\n" + "12345\r\n"); + DateTimeProvider.SetProvider(new ReproducibleDateTimeProvider(new DateTime(2024, 6, + 12, 15, 32, 0))); + + // Execute var output = Program.TallyBallots(_configFileName, _ballotDirectoryName); - Assert.That(output, Is.EqualTo(@"The election + // Verify + Assert.That(output, Is.EqualTo(@$"The election ============ Total of 3 ballots, thereof 1 at least partially invalid. @@ -140,7 +149,7 @@ 1. Dagobert Duck (4 points) 2. Mickey Mouse (3 points) Donald Duck (2 points) Daisy Duck (0 points) -(3 ballots, thereof 0 invalid) +(3 ballots, thereof 0 invalid; max 6 points) Election2 --------- @@ -150,6 +159,7 @@ Daisy Duck (0 points) Four: 0 J, 0 N, 2 E (3 ballots, thereof 1 invalid) +(DigiTally version {GitVersionInformation.SemVer}; report executed 2024-06-12 15:32) ")); } diff --git a/DigiTallyTests/DigiTallyTests.csproj b/DigiTallyTests/DigiTallyTests.csproj index af1def4..b7a7374 100644 --- a/DigiTallyTests/DigiTallyTests.csproj +++ b/DigiTallyTests/DigiTallyTests.csproj @@ -7,12 +7,14 @@ bin/$(Configuration) + - + + diff --git a/DigiTallyTests/ReadBallotsTests.cs b/DigiTallyTests/ReadBallotsTests.cs index cd52a99..7cb2e4a 100644 --- a/DigiTallyTests/ReadBallotsTests.cs +++ b/DigiTallyTests/ReadBallotsTests.cs @@ -2,10 +2,13 @@ // This software is licensed under the GNU General Public License version 3 // (https://opensource.org/licenses/GPL-3.0) +using System; using System.Collections.Generic; using System.IO; using System.Linq; using NUnit.Framework; +using SIL.Providers; +using SIL.TestUtilities.Providers; namespace DigitaleBriefwahl.Tally.Tests { @@ -194,6 +197,8 @@ public void AddBallot_BothInvalid() [Test] public void GetResultString_Valid_OnlyOneNominee() { + DateTimeProvider.SetProvider(new ReproducibleDateTimeProvider(new DateTime(2024, 6, + 12, 15, 32, 0))); File.WriteAllText(_configFileName, @"[Wahlen] Titel=The election Wahl1=Election @@ -226,11 +231,12 @@ public void GetResultString_Valid_OnlyOneNominee() var election1 = sut.Results.First(); Assert.That(election1.Key.BallotsProcessed, Is.EqualTo(1)); Assert.That(election1.Key.Invalid, Is.EqualTo(0)); - Assert.That(sut.GetResultString(), Is.EqualTo(@"Election + Assert.That(sut.GetResultString(), Is.EqualTo($@"Election -------- 1. Mickey Mouse (1 points) -(1 ballots, thereof 0 invalid) +(1 ballots, thereof 0 invalid; max 2 points) +(DigiTally version {GitVersionInformation.SemVer}; report executed 2024-06-12 15:32) ")); } diff --git a/DigiTallyTests/ReadBallotsTests_Weighted.cs b/DigiTallyTests/ReadBallotsTests_Weighted.cs index 7179787..b309527 100644 --- a/DigiTallyTests/ReadBallotsTests_Weighted.cs +++ b/DigiTallyTests/ReadBallotsTests_Weighted.cs @@ -1,12 +1,16 @@ // Copyright (c) 2024 Eberhard Beilharz // This software is licensed under the GNU General Public License version 3 // (https://opensource.org/licenses/GPL-3.0) + +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using DigitaleBriefwahl.Model; using NUnit.Framework; +using SIL.Providers; +using SIL.TestUtilities.Providers; namespace DigitaleBriefwahl.Tally.Tests { @@ -43,6 +47,8 @@ public void Setup() Kandidat3=Dagobert Duck Kandidat4=Daisy Duck "); + DateTimeProvider.SetProvider(new ReproducibleDateTimeProvider(new DateTime(2024, 6, + 12, 15, 32, 0))); } [TearDown] @@ -283,14 +289,15 @@ public void GetResultString() _ballotFileNames.Add(ballotFileName); var sut = new ReadBallots(_configFileName); Assert.That(sut.AddBallot(ballotFileName), Is.True); - Assert.That(sut.GetResultString(), Is.EqualTo(@"Election + Assert.That(sut.GetResultString(), Is.EqualTo($@"Election -------- 1. Dagobert Duck (2 points) 2. Mickey Mouse (1 points) Daisy Duck (0 points) Donald Duck (0 points) -(1 ballots, thereof 0 invalid) +(1 ballots, thereof 0 invalid; max 2 points) +(DigiTally version {GitVersionInformation.SemVer}; report executed 2024-06-12 15:32) ")); } @@ -330,14 +337,15 @@ public void GetResultString_SameVotes() var sut = new ReadBallots(_configFileName); Assert.That(sut.AddBallot(ballotFileName1), Is.True); Assert.That(sut.AddBallot(ballotFileName2), Is.True); - Assert.That(sut.GetResultString(), Is.EqualTo(@"Election + Assert.That(sut.GetResultString(), Is.EqualTo($@"Election -------- 1. Dagobert Duck (3 points) 1. Mickey Mouse (3 points) Daisy Duck (0 points) Donald Duck (0 points) -(2 ballots, thereof 0 invalid) +(2 ballots, thereof 0 invalid; max 4 points) +(DigiTally version {GitVersionInformation.SemVer}; report executed 2024-06-12 15:32) ")); } @@ -361,14 +369,15 @@ public void GetResultString_Abstains() _ballotFileNames.Add(ballotFileName); var sut = new ReadBallots(_configFileName); Assert.That(sut.AddBallot(ballotFileName), Is.True); - Assert.That(sut.GetResultString(), Is.EqualTo(@"Election + Assert.That(sut.GetResultString(), Is.EqualTo($@"Election -------- Dagobert Duck (0 points) Daisy Duck (0 points) Donald Duck (0 points) Mickey Mouse (0 points) -(1 ballots, thereof 0 invalid) +(1 ballots, thereof 0 invalid; max 2 points) +(DigiTally version {GitVersionInformation.SemVer}; report executed 2024-06-12 15:32) ")); } diff --git a/DigiTallyTests/ReadBallotsTests_YesNo.cs b/DigiTallyTests/ReadBallotsTests_YesNo.cs index 221db7c..7defdb0 100644 --- a/DigiTallyTests/ReadBallotsTests_YesNo.cs +++ b/DigiTallyTests/ReadBallotsTests_YesNo.cs @@ -2,12 +2,15 @@ // This software is licensed under the GNU General Public License version 3 // (https://opensource.org/licenses/GPL-3.0) +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using DigitaleBriefwahl.Model; using NUnit.Framework; +using SIL.Providers; +using SIL.TestUtilities.Providers; namespace DigitaleBriefwahl.Tally.Tests { @@ -279,6 +282,8 @@ public void YesNoElection_Valid_Incomplete_NoSpace() [Test] public void GetResultString() { + DateTimeProvider.SetProvider(new ReproducibleDateTimeProvider(new DateTime(2024, 6, + 12, 15, 32, 0))); var ballotFileName = Path.GetTempFileName(); File.WriteAllText(ballotFileName, "The election\r\n" + "============\r\n" + @@ -296,7 +301,7 @@ public void GetResultString() _ballotFileNames.Add(ballotFileName); var sut = new ReadBallots(_configFileName); Assert.That(sut.AddBallot(ballotFileName), Is.True); - Assert.That(sut.GetResultString(), Is.EqualTo(@"Election + Assert.That(sut.GetResultString(), Is.EqualTo($@"Election -------- Mickey Mouse: 1 J, 0 N, 0 E Donald Duck: 0 J, 1 N, 0 E @@ -304,12 +309,15 @@ public void GetResultString() Daisy Duck: 0 J, 0 N, 1 E (1 ballots, thereof 0 invalid) +(DigiTally version {GitVersionInformation.SemVer}; report executed 2024-06-12 15:32) ")); } [Test] public void GetResultString_DifferentOrder() { + DateTimeProvider.SetProvider(new ReproducibleDateTimeProvider(new DateTime(2024, 6, + 12, 15, 32, 0))); var ballotFileName = Path.GetTempFileName(); File.WriteAllText(ballotFileName, "The election\r\n" + "============\r\n" + @@ -327,7 +335,7 @@ public void GetResultString_DifferentOrder() _ballotFileNames.Add(ballotFileName); var sut = new ReadBallots(_configFileName); Assert.That(sut.AddBallot(ballotFileName), Is.True); - Assert.That(sut.GetResultString(), Is.EqualTo(@"Election + Assert.That(sut.GetResultString(), Is.EqualTo($@"Election -------- Mickey Mouse: 1 J, 0 N, 0 E Donald Duck: 0 J, 1 N, 0 E @@ -335,6 +343,7 @@ public void GetResultString_DifferentOrder() Daisy Duck: 0 J, 0 N, 1 E (1 ballots, thereof 0 invalid) +(DigiTally version {GitVersionInformation.SemVer}; report executed 2024-06-12 15:32) ")); } diff --git a/DigitaleBriefwahl.ExceptionHandlingTests/DigitaleBriefwahl.ExceptionHandlingTests.csproj b/DigitaleBriefwahl.ExceptionHandlingTests/DigitaleBriefwahl.ExceptionHandlingTests.csproj index 7664140..92cdec1 100644 --- a/DigitaleBriefwahl.ExceptionHandlingTests/DigitaleBriefwahl.ExceptionHandlingTests.csproj +++ b/DigitaleBriefwahl.ExceptionHandlingTests/DigitaleBriefwahl.ExceptionHandlingTests.csproj @@ -6,7 +6,7 @@ - + diff --git a/DigitaleBriefwahl/Model/CandidateResult.cs b/DigitaleBriefwahl/Model/CandidateResult.cs index 90d298f..fe70951 100644 --- a/DigitaleBriefwahl/Model/CandidateResult.cs +++ b/DigitaleBriefwahl/Model/CandidateResult.cs @@ -6,5 +6,15 @@ public abstract class CandidateResult { public int Invalid { get; protected set; } public abstract void CopyFrom(CandidateResult other); + + public override bool Equals(object obj) + { + return obj is CandidateResult other && Invalid == other.Invalid; + } + + public override int GetHashCode() + { + return 37 * Invalid; + } } } \ No newline at end of file diff --git a/DigitaleBriefwahl/Model/ElectionModel.cs b/DigitaleBriefwahl/Model/ElectionModel.cs index 8b75fbb..8fde964 100644 --- a/DigitaleBriefwahl/Model/ElectionModel.cs +++ b/DigitaleBriefwahl/Model/ElectionModel.cs @@ -141,7 +141,12 @@ public Dictionary ReadVotesFromBallot(StreamReader stre public virtual string GetResultString(Dictionary results) { - return $"({BallotsProcessed} ballots, thereof {Invalid} invalid)"; + return $"({GetResultStringSummary(results)})"; + } + + protected virtual string GetResultStringSummary(Dictionary results) + { + return $"{BallotsProcessed} ballots, thereof {Invalid} invalid"; } public abstract bool SkipNominee(string name, int iVote); diff --git a/DigitaleBriefwahl/Model/WeightedCandidateResult.cs b/DigitaleBriefwahl/Model/WeightedCandidateResult.cs index 393186d..750734c 100644 --- a/DigitaleBriefwahl/Model/WeightedCandidateResult.cs +++ b/DigitaleBriefwahl/Model/WeightedCandidateResult.cs @@ -2,6 +2,24 @@ namespace DigitaleBriefwahl.Model { public class WeightedCandidateResult: CandidateResult { + /// + /// Default c'tor + /// + public WeightedCandidateResult() + { + } + + /// + /// C'tor for unit tests + /// + /// + /// + public WeightedCandidateResult(int invalid, int points) + { + Invalid = invalid; + Points = points; + } + public int Points { get; internal set; } public override void CopyFrom(CandidateResult other) @@ -9,5 +27,18 @@ public override void CopyFrom(CandidateResult other) if (other is WeightedCandidateResult result) Points += result.Points; } + + public override bool Equals(object obj) + { + return base.Equals(obj) && obj is WeightedCandidateResult other && other.Points == Points; + } + + public override int GetHashCode() + { + var result = 17; + result = 19 * result + base.GetHashCode(); + result = 19 * result + Points; + return result; + } } } \ No newline at end of file diff --git a/DigitaleBriefwahl/Model/WeightedElectionModel.cs b/DigitaleBriefwahl/Model/WeightedElectionModel.cs index 2a55d1c..ccbf7de 100644 --- a/DigitaleBriefwahl/Model/WeightedElectionModel.cs +++ b/DigitaleBriefwahl/Model/WeightedElectionModel.cs @@ -218,10 +218,15 @@ public override string GetResultString(Dictionary resul bldr.AppendLine($"{placing} {candidate} ({weightedResult.Points} points)"); } - bldr.AppendLine(base.GetResultString(results)); + bldr.AppendLine(GetResultStringSummary(results)); return bldr.ToString(); } + protected override string GetResultStringSummary(Dictionary results) + { + return $"({base.GetResultStringSummary(results)}; max {(BallotsProcessed - Invalid) * Votes} points)"; + } + public override bool SkipNominee(string name, int iVote) { var vote = iVote + 1; diff --git a/DigitaleBriefwahl/Model/YesNoCandidateResult.cs b/DigitaleBriefwahl/Model/YesNoCandidateResult.cs index dbf1d68..6a6b48c 100644 --- a/DigitaleBriefwahl/Model/YesNoCandidateResult.cs +++ b/DigitaleBriefwahl/Model/YesNoCandidateResult.cs @@ -1,3 +1,5 @@ +using System.Net; + namespace DigitaleBriefwahl.Model { public class YesNoCandidateResult: CandidateResult @@ -15,5 +17,21 @@ public override void CopyFrom(CandidateResult other) No += result.No; Abstention += result.Abstention; } + + public override bool Equals(object obj) + { + return base.Equals(obj) && obj is YesNoCandidateResult other && other.Yes == Yes && + other.No == No && other.Abstention == Abstention; + } + + public override int GetHashCode() + { + var result = 23; + result = 29 * result + base.GetHashCode(); + result = 29 * result + Yes; + result = 29 * result + No; + result = 29 * result + Abstention; + return result; + } } } \ No newline at end of file diff --git a/DigitaleBriefwahlTests/DigitaleBriefwahlTests.csproj b/DigitaleBriefwahlTests/DigitaleBriefwahlTests.csproj index 6cfd648..4cb15c9 100644 --- a/DigitaleBriefwahlTests/DigitaleBriefwahlTests.csproj +++ b/DigitaleBriefwahlTests/DigitaleBriefwahlTests.csproj @@ -8,7 +8,7 @@ - + diff --git a/DigitaleBriefwahlTests/Encryption/DecryptHelper.cs b/DigitaleBriefwahlTests/Encryption/DecryptHelper.cs index 3dc8bd7..03cfd6e 100644 --- a/DigitaleBriefwahlTests/Encryption/DecryptHelper.cs +++ b/DigitaleBriefwahlTests/Encryption/DecryptHelper.cs @@ -13,10 +13,9 @@ private static PgpPrivateKey GetPrivateKey(string privateKeyPath, char[] passPhr using Stream inputStream = PgpUtilities.GetDecoderStream(keyIn); PgpSecretKeyRingBundle secretKeyRingBundle = new PgpSecretKeyRingBundle(inputStream); - PgpSecretKey key = null; - foreach (PgpSecretKeyRing kRing in secretKeyRingBundle.GetKeyRings()) + foreach (var kRing in secretKeyRingBundle.GetKeyRings()) { - foreach (PgpSecretKey secretKey in kRing.GetSecretKeys()) + foreach (var secretKey in kRing.GetSecretKeys()) { return secretKey.ExtractPrivateKey(passPhrase); } diff --git a/DigitaleBriefwahlTests/ElectionModelFactoryTests.cs b/DigitaleBriefwahlTests/Model/ElectionModelFactoryTests.cs similarity index 96% rename from DigitaleBriefwahlTests/ElectionModelFactoryTests.cs rename to DigitaleBriefwahlTests/Model/ElectionModelFactoryTests.cs index 1f0757f..e842e0d 100644 --- a/DigitaleBriefwahlTests/ElectionModelFactoryTests.cs +++ b/DigitaleBriefwahlTests/Model/ElectionModelFactoryTests.cs @@ -6,7 +6,7 @@ using DigitaleBriefwahl.Model; using NUnit.Framework; -namespace DigitaleBriefwahlTests +namespace DigitaleBriefwahlTests.Model { [TestFixture] public class ElectionModelFactoryTests diff --git a/DigitaleBriefwahlTests/ElectionModelTests.cs b/DigitaleBriefwahlTests/Model/ElectionModelTests.cs similarity index 99% rename from DigitaleBriefwahlTests/ElectionModelTests.cs rename to DigitaleBriefwahlTests/Model/ElectionModelTests.cs index 6730e12..e830172 100644 --- a/DigitaleBriefwahlTests/ElectionModelTests.cs +++ b/DigitaleBriefwahlTests/Model/ElectionModelTests.cs @@ -1,6 +1,7 @@ // Copyright (c) 2016 Eberhard Beilharz // This software is licensed under the GNU General Public License version 3 // (https://opensource.org/licenses/GPL-3.0) + using System; using System.IO; using DigitaleBriefwahl; @@ -9,7 +10,7 @@ using IniParser.Model; using NUnit.Framework; -namespace DigitaleBriefwahlTests +namespace DigitaleBriefwahlTests.Model { [TestFixture] public class ElectionModelTests diff --git a/DigitaleBriefwahlTests/WeightedElectionModelTests.cs b/DigitaleBriefwahlTests/Model/WeightedElectionModelTests.cs similarity index 52% rename from DigitaleBriefwahlTests/WeightedElectionModelTests.cs rename to DigitaleBriefwahlTests/Model/WeightedElectionModelTests.cs index eda8422..ddeafd1 100644 --- a/DigitaleBriefwahlTests/WeightedElectionModelTests.cs +++ b/DigitaleBriefwahlTests/Model/WeightedElectionModelTests.cs @@ -3,34 +3,50 @@ // (https://opensource.org/licenses/GPL-3.0) using System; +using System.Collections; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Text; using DigitaleBriefwahl.Model; using NUnit.Framework; -namespace DigitaleBriefwahlTests +namespace DigitaleBriefwahlTests.Model { [TestFixture] public class WeightedElectionModelTests { - [TestCase("Dagobert Duck\nMickey Mouse", false, ExpectedResult = "Election\r\n" + -"--------\r\n" + -"(2 Stimmen; Wahl der Reihenfolge nach mit 1.-2. kennzeichnen)\r\n" + -"2. Mickey Mouse\r\n" + -" Donald Duck\r\n" + -"1. Dagobert Duck\r\n")] - [TestCase("Donald Duck\nDagobert Duck", false, ExpectedResult = "Election\r\n" + -"--------\r\n" + -"(2 Stimmen; Wahl der Reihenfolge nach mit 1.-2. kennzeichnen)\r\n" + -" Mickey Mouse\r\n" + -"1. Donald Duck\r\n" + -"2. Dagobert Duck\r\n")] - [TestCase("", true, ExpectedResult = "Election\r\n" + -"--------\r\n" + -"(2 Stimmen; Wahl der Reihenfolge nach mit 1.-2. kennzeichnen)\r\n" + -" Mickey Mouse\r\n" + -" Donald Duck\r\n" + -" Dagobert Duck\r\n")] + private const string BallotDagobertMickey = "Election\r\n" + + "--------\r\n" + + "(2 Stimmen; Wahl der Reihenfolge nach mit 1.-2. kennzeichnen)\r\n" + + "2. Mickey Mouse\r\n" + + " Donald Duck\r\n" + + "1. Dagobert Duck\r\n"; + + private const string BallotDonaldDagobert = "Election\r\n" + + "--------\r\n" + + "(2 Stimmen; Wahl der Reihenfolge nach mit 1.-2. kennzeichnen)\r\n" + + " Mickey Mouse\r\n" + + "1. Donald Duck\r\n" + + "2. Dagobert Duck\r\n"; + + private const string BallotDonaldOnly = "Election\r\n" + + "--------\r\n" + + "(2 Stimmen; Wahl der Reihenfolge nach mit 1.-2. kennzeichnen)\r\n" + + " Mickey Mouse\r\n" + + "1. Donald Duck\r\n" + + " Dagobert Duck\r\n"; + + private const string BallotNone = "Election\r\n" + + "--------\r\n" + + "(2 Stimmen; Wahl der Reihenfolge nach mit 1.-2. kennzeichnen)\r\n" + + " Mickey Mouse\r\n" + + " Donald Duck\r\n" + + " Dagobert Duck\r\n"; + + [TestCase("Dagobert Duck\nMickey Mouse", false, ExpectedResult = BallotDagobertMickey)] + [TestCase("Donald Duck\nDagobert Duck", false, ExpectedResult = BallotDonaldDagobert)] + [TestCase("", true, ExpectedResult = BallotNone)] public string GetResult(string electedNominees, bool writeEmptyBallot) { // Setup @@ -179,5 +195,88 @@ public void GetInvalidVotes_IncompleteOk(string[] votes, int expectedInvalid) Assert.That(result.Count, Is.EqualTo(0)); } + + [TestCase(BallotDagobertMickey, new[] { "Mickey Mouse:0:1", "Donald Duck:0:0", "Dagobert Duck:0:2" })] + [TestCase(BallotDonaldDagobert, new[] { "Mickey Mouse:0:0", "Donald Duck:0:2", "Dagobert Duck:0:1" })] + [TestCase(BallotDonaldOnly, new[] { "Mickey Mouse:0:0", "Donald Duck:0:2", "Dagobert Duck:0:0" })] + [TestCase(BallotNone, new[] { "Mickey Mouse:0:0", "Donald Duck:0:0", "Dagobert Duck:0:0" })] + public void ReadVotesFromBallot(string ballot, string[] expectedResultStrings) + { + // Setup + const string ini = @"[Election] +Text=Some description +Typ=Weighted +Stimmen=2 +Kandidat1=Mickey Mouse +Kandidat2=Donald Duck +Kandidat3=Dagobert Duck +"; + var data = ElectionModelTests.ReadIniDataFromString(ini); + var model = ElectionModelFactory.Create("Election", data); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(ballot.Replace("\r", ""))); + using var reader = new StreamReader(stream); + // skip first two lines of ballot + reader.ReadLine(); + reader.ReadLine(); + + // Execute + var results = model.ReadVotesFromBallot(reader, null); + + // Verify + var expectedResults = new Dictionary(); + foreach (var expectedString in expectedResultStrings) + { + var split = expectedString.Split(':'); + expectedResults.Add(split[0], new WeightedCandidateResult(int.Parse(split[1]), + int.Parse(split[2]))); + } + + Assert.That(results, Is.EqualTo(expectedResults)); + } + + [TestCase(BallotDagobertMickey, ExpectedResult = @"1. Dagobert Duck (2 points) +2. Mickey Mouse (1 points) + Donald Duck (0 points) +(1 ballots, thereof 0 invalid; max 2 points) +")] + [TestCase(BallotDonaldDagobert, ExpectedResult = @"1. Donald Duck (2 points) +2. Dagobert Duck (1 points) + Mickey Mouse (0 points) +(1 ballots, thereof 0 invalid; max 2 points) +")] + [TestCase(BallotDonaldOnly, ExpectedResult = @"1. Donald Duck (2 points) + Dagobert Duck (0 points) + Mickey Mouse (0 points) +(1 ballots, thereof 0 invalid; max 2 points) +")] + [TestCase(BallotNone, ExpectedResult = @" Dagobert Duck (0 points) + Donald Duck (0 points) + Mickey Mouse (0 points) +(1 ballots, thereof 0 invalid; max 2 points) +")] + public string GetResultString(string ballot) + { + // Setup + const string ini = @"[Election] +Text=Some description +Typ=Weighted +Stimmen=2 +Kandidat1=Mickey Mouse +Kandidat2=Donald Duck +Kandidat3=Dagobert Duck +"; + var data = ElectionModelTests.ReadIniDataFromString(ini); + var model = ElectionModelFactory.Create("Election", data); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(ballot.Replace("\r", ""))); + using var reader = new StreamReader(stream); + // skip first two lines of ballot + reader.ReadLine(); + reader.ReadLine(); + var results = model.ReadVotesFromBallot(reader, null); + + // Execute + return model.GetResultString(results); + } + } } \ No newline at end of file diff --git a/DigitaleBriefwahlTests/YesNoElectionModelTests.cs b/DigitaleBriefwahlTests/Model/YesNoElectionModelTests.cs similarity index 98% rename from DigitaleBriefwahlTests/YesNoElectionModelTests.cs rename to DigitaleBriefwahlTests/Model/YesNoElectionModelTests.cs index 5708bd3..2456911 100644 --- a/DigitaleBriefwahlTests/YesNoElectionModelTests.cs +++ b/DigitaleBriefwahlTests/Model/YesNoElectionModelTests.cs @@ -7,7 +7,7 @@ using DigitaleBriefwahl.Model; using NUnit.Framework; -namespace DigitaleBriefwahlTests +namespace DigitaleBriefwahlTests.Model { [TestFixture] public class YesNoElectionModelTests