1
0
This repository has been archived on 2023-11-30. You can view files and clone it, but cannot push or open issues or pull requests.
dtux__serveur-vote-lalis/include/condorcet/Tests/src/Console/Commands/ElectionCommandTest.php

405 lines
15 KiB
PHP
Raw Normal View History

2022-09-21 12:39:11 +02:00
<?php
declare(strict_types=1);
namespace CondorcetPHP\Condorcet\Tests\Console\Commands;
use CondorcetPHP\Condorcet\Console\Commands\ElectionCommand;
use CondorcetPHP\Condorcet\Throwable\{CandidateExistsException, ResultRequestedWithoutVotesException};
use PHPUnit\Framework\TestCase;
use CondorcetPHP\Condorcet\Console\CondorcetApplication;
use CondorcetPHP\Condorcet\Console\Style\CondorcetStyle;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Tester\CommandTester;
class ElectionCommandTest extends TestCase
{
private readonly CommandTester $electionCommand;
protected function setUp(): void
{
CondorcetApplication::create();
$this->electionCommand = new CommandTester(CondorcetApplication::$SymfonyConsoleApplication->find('election'));
}
public function testConsoleSimpleElection(): void
{
$this->electionCommand->execute(
[
'--candidates' => 'A;B;C',
'--votes' => 'A>B>C;C>B>A;B>A>C',
'--stats' => null,
'--natural-condorcet' => null,
'--allows-votes-weight' => null,
'--no-tie' => null,
'--list-votes' => null,
'--deactivate-implicit-ranking' => null,
'--show-pairwise' => null,
],
[
'verbosity' => OutputInterface::VERBOSITY_VERBOSE,
]
);
$output = $this->electionCommand->getDisplay();
self::assertStringContainsString('3 candidates registered || 3 votes registered', $output);
self::assertStringContainsString('Schulze', $output);
self::assertStringContainsString('Registered candidates', $output);
self::assertStringContainsString('Stats - votes registration', $output);
self::assertStringContainsString('Registered Votes List', $output);
self::assertStringContainsString('Pairwise', $output);
self::assertStringContainsString('Stats:', $output);
self::assertMatchesRegularExpression('/Is vote weight allowed\?( )+TRUE/', $output);
self::assertMatchesRegularExpression('/Votes are evaluated according to the implicit ranking rule\?( )+FALSE./', $output);
self::assertMatchesRegularExpression('/Is vote tie in rank allowed\?( )+FALSE/', $output);
}
public function testConsoleSeats(): void
{
$this->electionCommand->execute(
[
'--candidates' => 'A;B;C',
'--votes' => 'A>B>C;C>B>A;B>A>C',
'--stats' => null,
'--natural-condorcet' => null,
'--allows-votes-weight' => null,
'--no-tie' => null,
'--list-votes' => null,
'--deactivate-implicit-ranking' => null,
'--show-pairwise' => null,
'--seats' => 42,
'methods' => ['STV'],
],
[
'verbosity' => OutputInterface::VERBOSITY_VERBOSE,
]
);
$output = $this->electionCommand->getDisplay();
self::assertStringContainsString('3 candidates registered || 3 votes registered', $output);
self::assertStringContainsString('Seats:', $output);
self::assertStringContainsString('42', $output);
}
public function testQuotas(): void
{
$this->electionCommand->execute([
'--candidates' => 'A;B;C',
'--votes' => 'A>B>C;C>B>A;B>A>C',
'methods' => ['STV'],
]);
$output = $this->electionCommand->getDisplay();
self::assertMatchesRegularExpression('/Is vote tie in rank allowed\?( )+TRUE/', $output);
self::assertStringContainsString('Droop Quota', $output);
$this->electionCommand->execute([
'--candidates' => 'A;B;C',
'--votes' => 'A>B>C;C>B>A;B>A>C',
'methods' => ['STV'],
'--quota' => 'imperiali',
]);
$output = $this->electionCommand->getDisplay();
self::assertStringContainsString('Imperiali', $output);
}
public function testConsoleAllMethodsArgument(): void
{
$this->electionCommand->execute([
'--candidates' => 'A;B;C',
'--votes' => 'A>B>C;C>B>A;B>A>C',
'methods' => ['all'],
]);
$output = $this->electionCommand->getDisplay();
// \var_dump($output);
self::assertStringContainsString('Copeland', $output);
}
public function testConsoleMultiplesMethods(): void
{
$this->electionCommand->execute([
'--candidates' => 'A;B;C',
'--votes' => 'A>B>C;C>B>A;B>A>C',
'methods' => ['Copeland', 'RankedPairs', 'Minimax'],
]);
$output = $this->electionCommand->getDisplay();
// \var_dump($output);
self::assertStringContainsString('Copeland', $output);
self::assertStringContainsString('Ranked Pairs M', $output);
self::assertStringContainsString('Minimax Winning', $output);
}
public function testConsoleFileInput(): void
{
$this->electionCommand->execute([
'--candidates' => __DIR__.'/data.candidates',
'--votes' => __DIR__.'/data.votes',
]);
$output = $this->electionCommand->getDisplay();
// \var_dump($output);
self::assertStringContainsString('Schulze', $output);
self::assertStringContainsString('A,B', $output);
self::assertStringContainsString('C '.CondorcetStyle::CONDORCET_LOSER_SYMBOL, $output);
}
public function testInteractiveCommand(): void
{
$this->electionCommand->setInputs([
'A',
'B',
'C',
'',
'A>B>C',
'B>A>C',
'A>C>B',
'',
]);
$this->electionCommand->execute([
'command' => 'election',
]);
$output = $this->electionCommand->getDisplay();
// \var_dump($output);
self::assertStringContainsString('Results: Schulze Winning', $output);
}
public function testNonInteractionMode(): never
{
$this->expectException(ResultRequestedWithoutVotesException::class);
$this->expectExceptionMessage('The result cannot be requested without votes');
$this->electionCommand->execute([], ['interactive' => false]);
// $output = $this->electionCommand->getDisplay();
// \var_dump($output);
}
public function testCustomizeVotesPerMb(): void
{
$this->electionCommand->execute([
'--candidates' => 'A;B;C',
'--votes' => 'A>B>C;C>B>A;B>A>C',
'--votes-per-mb' => 42,
]);
self::assertSame(42, \CondorcetPHP\Condorcet\Console\Commands\ElectionCommand::$VotesPerMB);
// $output = $this->electionCommand->getDisplay();
// \var_dump($output);
}
public function testVoteWithDb1(): void
{
ElectionCommand::$forceIniMemoryLimitTo = '128M';
$this->electionCommand->execute([
'--candidates' => 'A;B;C',
'--votes-per-mb' => 1,
'--votes' => 'A>B>C * '.(((int) preg_replace('`[^0-9]`', '', ElectionCommand::$forceIniMemoryLimitTo)) + 1), # Must be superior to memory limit in MB
], [
'verbosity' => OutputInterface::VERBOSITY_DEBUG,
]);
$output = $this->electionCommand->getDisplay();
self::assertMatchesRegularExpression('/Votes per Mb +1/', $output);
self::assertMatchesRegularExpression('/Db is used +yes, using path\\:/', $output);
ElectionCommand::$forceIniMemoryLimitTo = null;
# And absence of this error: unlink(path): Resource temporarily unavailable
}
public function testNaturalCondorcet(): void
{
$this->electionCommand->execute([
'--candidates' => 'A;B;C',
'--votes' => 'A=B=C',
'--natural-condorcet' => true,
]);
$output = $this->electionCommand->getDisplay();
self::assertStringContainsString(CondorcetStyle::CONDORCET_WINNER_SYMBOL.' Condorcet Winner | -', $output);
self::assertStringContainsString(CondorcetStyle::CONDORCET_LOSER_SYMBOL.' Condorcet Loser | -', $output);
}
public function testFromCondorcetElectionFormat_DoubleCandidates(): void
{
$this->expectException(CandidateExistsException::class);
$this->electionCommand->execute(
[
'--candidates' => 'A;B;C',
'--import-condorcet-election-format' => __DIR__.'/../../Tools/Converters/CondorcetElectionFormatData/test1.cvotes',
],
[
'verbosity' => OutputInterface::VERBOSITY_VERBOSE,
]
);
}
public function testFromCondorcetElectionFormat_ArgumentpriorityAndDoubleVoteArgument(): void
{
$this->electionCommand->execute(
[
'--import-condorcet-election-format' => __DIR__.'/../../Tools/Converters/CondorcetElectionFormatData/test1.cvotes',
'--votes' => 'C>A',
'--deactivate-implicit-ranking' => null,
'--no-tie' => null,
'--allows-votes-weight' => null,
],
[
'verbosity' => OutputInterface::VERBOSITY_VERBOSE,
]
);
$output = $this->electionCommand->getDisplay();
self::assertStringContainsString('3 candidates registered || 2 votes registered', $output);
self::assertStringContainsString('Schulze', $output);
self::assertStringContainsString('Registered candidates', $output);
self::assertStringContainsString('Stats - votes registration', $output);
self::assertMatchesRegularExpression('/Is vote weight allowed\?( )+TRUE/', $output);
self::assertMatchesRegularExpression('/Votes are evaluated according to the implicit ranking rule\?( )+FALSE./', $output);
self::assertMatchesRegularExpression('/Is vote tie in rank allowed\?( )+FALSE/', $output);
self::assertStringContainsString('Sum vote weight | 3', $output);
}
public function testFromCondorcetElectionFormat_Arguments(): void
{
$this->electionCommand->execute(
[
'--import-condorcet-election-format' => __DIR__.'/../../Tools/Converters/CondorcetElectionFormatData/test2.cvotes',
],
[
'verbosity' => OutputInterface::VERBOSITY_VERBOSE,
]
);
$output = $this->electionCommand->getDisplay();
self::assertStringContainsString('3 candidates registered || 2 votes registered', $output);
self::assertStringContainsString('Schulze', $output);
self::assertStringContainsString('Registered candidates', $output);
self::assertStringContainsString('Stats - votes registration', $output);
self::assertMatchesRegularExpression('/Is vote weight allowed\?( )+FALSE/', $output);
self::assertMatchesRegularExpression('/Votes are evaluated according to the implicit ranking rule\?( )+FALSE./', $output);
self::assertMatchesRegularExpression('/Is vote tie in rank allowed\?( )+TRUE/', $output);
self::assertStringContainsString('Sum vote weight | 2', $output);
self::assertStringContainsString('B '.CondorcetStyle::CONDORCET_WINNER_SYMBOL, $output); # Condorcet Winner
}
public function testVoteWithDb_CondorcetElectionFormat(): void
{
ElectionCommand::$forceIniMemoryLimitTo = '128M';
$this->electionCommand->execute([
'--votes-per-mb' => 1,
'--import-condorcet-election-format' => __DIR__.'/../../Tools/Converters/CondorcetElectionFormatData/test3.cvotes',
], [
'verbosity' => OutputInterface::VERBOSITY_DEBUG,
]);
$output = $this->electionCommand->getDisplay();
self::assertMatchesRegularExpression('/Votes per Mb +1/', $output);
self::assertStringContainsString('Db is used', $output);
self::assertStringContainsString('yes, using path:', $output);
ElectionCommand::$forceIniMemoryLimitTo = null;
# And absence of this error: unlink(path): Resource temporarily unavailable
}
public function testFromDebianFormat(): void
{
$this->electionCommand->execute(
[
'--import-debian-format' => __DIR__.'/../../Tools/Converters/DebianData/leader2020_tally.txt',
'methods' => ['STV'],
],
[
'verbosity' => OutputInterface::VERBOSITY_VERBOSE,
]
);
$output = $this->electionCommand->getDisplay();
self::assertStringContainsString('4 candidates registered || 339 votes registered', $output);
self::assertStringContainsString('STV', $output);
self::assertStringContainsString('Registered candidates', $output);
self::assertStringContainsString('Stats - votes registration', $output);
self::assertMatchesRegularExpression('/Is vote weight allowed\?( )+FALSE/', $output);
self::assertMatchesRegularExpression('/Votes are evaluated according to the implicit ranking rule\?( )+TRUE./', $output);
self::assertMatchesRegularExpression('/Is vote tie in rank allowed\?( )+TRUE/', $output);
self::assertStringContainsString('Sum vote weight | 339', $output);
self::assertStringContainsString('Jonathan Carter '.CondorcetStyle::CONDORCET_WINNER_SYMBOL, $output); # Condorcet Winner
self::assertMatchesRegularExpression('/Seats: *\| 1/', $output);
}
public function testFromDavidHillFormat(): void
{
$this->electionCommand->execute(
[
'--import-david-hill-format' => __DIR__.'/../../Tools/Converters/TidemanData/A1.HIL',
'methods' => ['STV'],
],
[
'verbosity' => OutputInterface::VERBOSITY_VERBOSE,
]
);
$output = $this->electionCommand->getDisplay();
self::assertStringContainsString('10 candidates registered || 380 votes registered', $output);
self::assertStringContainsString('STV', $output);
self::assertStringContainsString('Registered candidates', $output);
self::assertStringContainsString('Stats - votes registration', $output);
self::assertMatchesRegularExpression('/Is vote weight allowed\?( )+FALSE/', $output);
self::assertMatchesRegularExpression('/Votes are evaluated according to the implicit ranking rule\?( )+TRUE./', $output);
self::assertMatchesRegularExpression('/Is vote tie in rank allowed\?( )+TRUE/', $output);
self::assertStringContainsString('Sum vote weight | 380', $output);
self::assertStringContainsString('Candidate 1 '.CondorcetStyle::CONDORCET_WINNER_SYMBOL, $output); # Condorcet Winner
self::assertMatchesRegularExpression('/Seats: *\| 3/', $output);
}
}