mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	[yul-phaser] Replace mutation tests with hard-coded expectations with more robust ones that check the statistical distribution
- The old tests would easily break when adding/removing optimiser steps.
This commit is contained in:
		
							parent
							
								
									d75f0ba437
								
							
						
					
					
						commit
						5637bdcaec
					
				| @ -22,6 +22,7 @@ | ||||
| #include <tools/yulPhaser/SimulationRNG.h> | ||||
| 
 | ||||
| #include <libsolutil/CommonIO.h> | ||||
| #include <libyul/optimiser/Suite.h> | ||||
| 
 | ||||
| #include <boost/test/unit_test.hpp> | ||||
| #include <boost/algorithm/string/predicate.hpp> | ||||
| @ -31,6 +32,7 @@ | ||||
| 
 | ||||
| using namespace std; | ||||
| using namespace solidity::util; | ||||
| using namespace solidity::yul; | ||||
| 
 | ||||
| namespace solidity::phaser::test | ||||
| { | ||||
| @ -41,19 +43,32 @@ BOOST_AUTO_TEST_SUITE(GeneRandomisationTest) | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(geneRandomisation_should_iterate_over_genes_and_replace_them_with_random_ones_with_given_probability) | ||||
| { | ||||
| 	Chromosome chromosome("fcCUnDvejs"); | ||||
| 	function<Mutation> mutation01 = geneRandomisation(0.1); | ||||
| 	function<Mutation> mutation05 = geneRandomisation(0.5); | ||||
| 	function<Mutation> mutation10 = geneRandomisation(1.0); | ||||
| 	size_t constexpr inputLength = 1000; | ||||
| 	double constexpr tolerance = 0.05; | ||||
| 
 | ||||
| 	// Use genes that do not represent valid step abbreviations to be able to easily spot added steps.
 | ||||
| 	assert(OptimiserSuite::stepAbbreviationToNameMap().count('.') == 0); | ||||
| 	Chromosome input = Chromosome(string(inputLength, '.')); | ||||
| 
 | ||||
| 	SimulationRNG::reset(1); | ||||
| 	BOOST_TEST(countDifferences(mutation01(chromosome), chromosome), 2); | ||||
| 	BOOST_TEST(countDifferences(mutation05(chromosome), chromosome), 5); | ||||
| 	BOOST_TEST(countDifferences(mutation10(chromosome), chromosome), 7); | ||||
| 	SimulationRNG::reset(2); | ||||
| 	BOOST_TEST(countDifferences(mutation01(chromosome), chromosome), 1); | ||||
| 	BOOST_TEST(countDifferences(mutation05(chromosome), chromosome), 3); | ||||
| 	BOOST_TEST(countDifferences(mutation10(chromosome), chromosome), 9); | ||||
| 	for (size_t randomisationChancePercent = 20; randomisationChancePercent <= 100; randomisationChancePercent += 20) | ||||
| 	{ | ||||
| 		double const randomisationChance = (randomisationChancePercent / 100.0); | ||||
| 
 | ||||
| 		Chromosome output = geneRandomisation(randomisationChance)(input); | ||||
| 		string outputGenes = output.genes(); | ||||
| 		BOOST_REQUIRE(output.length() == input.length()); | ||||
| 
 | ||||
| 		double const expectedValue = randomisationChance; | ||||
| 		double const variance = randomisationChance * (1 - randomisationChance); | ||||
| 		double const randomisedGeneCount = input.length() - static_cast<size_t>(count(outputGenes.begin(), outputGenes.end(), '.')); | ||||
| 		double const squaredError = | ||||
| 			(inputLength - randomisedGeneCount) * expectedValue * expectedValue + | ||||
| 			randomisedGeneCount * (1 - expectedValue) * (1 - expectedValue); | ||||
| 
 | ||||
| 		BOOST_TEST(abs(randomisedGeneCount / inputLength - expectedValue) < tolerance); | ||||
| 		BOOST_TEST(abs(squaredError / inputLength - variance) < tolerance); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(geneRandomisation_should_return_identical_chromosome_if_probability_is_zero) | ||||
| @ -66,17 +81,33 @@ BOOST_AUTO_TEST_CASE(geneRandomisation_should_return_identical_chromosome_if_pro | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(geneDeletion_should_iterate_over_genes_and_delete_them_with_given_probability) | ||||
| { | ||||
| 	Chromosome chromosome("fcCUnDvejs"); | ||||
| 	function<Mutation> mutation01 = geneDeletion(0.1); | ||||
| 	function<Mutation> mutation05 = geneDeletion(0.5); | ||||
| 	size_t constexpr inputLength = 1000; | ||||
| 	double constexpr tolerance = 0.05; | ||||
| 
 | ||||
| 	// Use genes that do not represent valid step abbreviations to be able to easily spot added steps.
 | ||||
| 	assert(OptimiserSuite::stepAbbreviationToNameMap().count('.') == 0); | ||||
| 	Chromosome input = Chromosome(string(inputLength, '.')); | ||||
| 
 | ||||
| 	SimulationRNG::reset(1); | ||||
| 	//                                                               fcCUnDvejs
 | ||||
| 	BOOST_TEST(mutation01(chromosome) == Chromosome(stripWhitespace("fcCU Dvejs"))); | ||||
| 	BOOST_TEST(mutation05(chromosome) == Chromosome(stripWhitespace("     D ejs"))); | ||||
| 	SimulationRNG::reset(2); | ||||
| 	BOOST_TEST(mutation01(chromosome) == Chromosome(stripWhitespace("fcUnDvejs"))); | ||||
| 	BOOST_TEST(mutation05(chromosome) == Chromosome(stripWhitespace("  Un    s"))); | ||||
| 	for (size_t deletionChancePercent = 20; deletionChancePercent < 100; deletionChancePercent += 20) | ||||
| 	{ | ||||
| 		double const deletionChance = (deletionChancePercent / 100.0); | ||||
| 
 | ||||
| 		Chromosome output = geneDeletion(deletionChance)(input); | ||||
| 		string outputGenes = output.genes(); | ||||
| 		BOOST_REQUIRE(output.length() <= input.length()); | ||||
| 		BOOST_REQUIRE(static_cast<size_t>(count(outputGenes.begin(), outputGenes.end(), '.')) == output.length()); | ||||
| 
 | ||||
| 		double const expectedValue = deletionChance; | ||||
| 		double const variance = deletionChance * (1 - deletionChance); | ||||
| 		double const deletedGeneCount = input.length() - output.length(); | ||||
| 		double const squaredError = | ||||
| 			(inputLength - deletedGeneCount) * expectedValue * expectedValue + | ||||
| 			deletedGeneCount * (1 - expectedValue) * (1 - expectedValue); | ||||
| 
 | ||||
| 		BOOST_TEST(abs(deletedGeneCount / inputLength - expectedValue) < tolerance); | ||||
| 		BOOST_TEST(abs(squaredError / inputLength - variance) < tolerance); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(geneDeletion_should_return_identical_chromosome_if_probability_is_zero) | ||||
| @ -97,17 +128,37 @@ BOOST_AUTO_TEST_CASE(geneDeletion_should_delete_all_genes_if_probability_is_one) | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(geneAddition_should_iterate_over_gene_positions_and_insert_new_genes_with_given_probability) | ||||
| { | ||||
| 	Chromosome chromosome("fcCUnDvejs"); | ||||
| 	function<Mutation> mutation01 = geneAddition(0.1); | ||||
| 	function<Mutation> mutation05 = geneAddition(0.5); | ||||
| 	size_t constexpr inputLength = 1000; | ||||
| 	double constexpr tolerance = 0.05; | ||||
| 	size_t constexpr maxAdditions = inputLength + 1; | ||||
| 
 | ||||
| 	// Use genes that do not represent valid step abbreviations to be able to easily spot added steps.
 | ||||
| 	assert(OptimiserSuite::stepAbbreviationToNameMap().count('.') == 0); | ||||
| 	Chromosome input = Chromosome(string(inputLength, '.')); | ||||
| 
 | ||||
| 	SimulationRNG::reset(1); | ||||
| 	//                                                                 f  c  C  U  n  D  v  e  j  s
 | ||||
| 	BOOST_TEST(mutation01(chromosome) == Chromosome(stripWhitespace("  f  c  C  UC n  D  v  e  jx s")));  //  20% more
 | ||||
| 	BOOST_TEST(mutation05(chromosome) == Chromosome(stripWhitespace("s f  cu C  U  nj D  v  eO j  sf"))); //  50% more
 | ||||
| 	SimulationRNG::reset(2); | ||||
| 	BOOST_TEST(mutation01(chromosome) == Chromosome(stripWhitespace("  f  cp C  U  n  D  v  e  j  s")));  //  10% more
 | ||||
| 	BOOST_TEST(mutation05(chromosome) == Chromosome(stripWhitespace("M f  ce Ce U  n  D  v  e  jo s")));  //  40% more
 | ||||
| 	for (size_t additionChancePercent = 20; additionChancePercent < 100; additionChancePercent += 20) | ||||
| 	{ | ||||
| 		double const additionChance = (additionChancePercent / 100.0); | ||||
| 
 | ||||
| 		Chromosome output = geneAddition(additionChance)(input); | ||||
| 		BOOST_REQUIRE(output.length() >= input.length()); | ||||
| 		BOOST_REQUIRE(output.length() <= inputLength + maxAdditions); | ||||
| 
 | ||||
| 		string_view outputGenes = output.genes(); | ||||
| 		size_t preservedGeneCount = static_cast<size_t>(count(outputGenes.begin(), outputGenes.end(), '.')); | ||||
| 		BOOST_REQUIRE(preservedGeneCount == input.length()); | ||||
| 
 | ||||
| 		double const expectedValue = additionChance; | ||||
| 		double const variance = additionChance * (1 - additionChance); | ||||
| 		double const addedGeneCount = (output.length() - preservedGeneCount); | ||||
| 		double const squaredError = | ||||
| 			(maxAdditions - addedGeneCount) * expectedValue * expectedValue + | ||||
| 			addedGeneCount * (1 - expectedValue) * (1 - expectedValue); | ||||
| 
 | ||||
| 		BOOST_TEST(abs(addedGeneCount / maxAdditions - expectedValue) < tolerance); | ||||
| 		BOOST_TEST(abs(squaredError / maxAdditions - variance) < tolerance); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(geneAddition_should_be_able_to_insert_before_first_position) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user