Skip to content

Commit 25e14db

Browse files
committed
fixed few bugs based on broken invariant
1 parent d7ad11b commit 25e14db

7 files changed

Lines changed: 75 additions & 34 deletions

File tree

core/src/main/kotlin/org/evomaster/core/search/gene/collection/ArrayGene.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ class ArrayGene<T>(
141141
}
142142
if (this.template::class.simpleName != other.template::class.simpleName) return false
143143

144+
if(this.elements.size != other.elements.size) return false
145+
144146
return this.elements.zip(other.elements) { thisElem, otherElem ->
145147
thisElem.containsSameValueAs(otherElem)
146148
}.all { it }

core/src/main/kotlin/org/evomaster/core/search/gene/collection/EnumGene.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ class EnumGene<T : Comparable<T>>(
210210

211211
val phenotype = other.getPhenotype()
212212
when(phenotype) {
213-
is EnumGene<*> -> index == phenotype.index
213+
is EnumGene<*> -> index = phenotype.index
214214
else -> {
215215
// since the binding is derived, it is not always true.
216216
log.info("cannot bind EnumGene with ${phenotype::class.java.simpleName}")

core/src/main/kotlin/org/evomaster/core/search/gene/datetime/TimeGene.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,8 @@ class TimeGene(
201201
return when (gene) {
202202
is TimeGene -> {
203203
hour.unsafeCopyValueFrom(gene.hour)
204-
&& second.unsafeCopyValueFrom(gene.minute)
205-
&& minute.unsafeCopyValueFrom(gene.second)
204+
&& second.unsafeCopyValueFrom(gene.second)
205+
&& minute.unsafeCopyValueFrom(gene.minute)
206206
&& millisecond.unsafeCopyValueFrom(gene.millisecond)
207207
&& offset.unsafeCopyValueFrom(gene.offset)
208208
}

core/src/main/kotlin/org/evomaster/core/search/gene/sql/SqlRangeGene.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ class SqlRangeGene<T>(
9292
if (other !is SqlRangeGene<*>) {
9393
throw IllegalArgumentException("Invalid gene type ${other.javaClass}")
9494
}
95-
return isLeftClosed.containsSameValueAs(other.isRightClosed)
95+
return isLeftClosed.containsSameValueAs(other.isLeftClosed)
9696
&& left.containsSameValueAs(other.left as Gene)
9797
&& right.containsSameValueAs(other.right as Gene)
9898
&& isRightClosed.containsSameValueAs(other.isRightClosed)

core/src/main/kotlin/org/evomaster/core/search/gene/uri/UriGene.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ class UriGene(name: String,
8181
}
8282

8383
override fun unsafeCopyValueFrom(other: Gene): Boolean {
84+
if(other is UriGene){
85+
return gene.unsafeCopyValueFrom(other.gene)
86+
}
8487
return gene.unsafeCopyValueFrom(other)
8588
}
8689

core/src/main/kotlin/org/evomaster/core/search/gene/wrapper/FlexibleGene.kt

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -131,24 +131,17 @@ class FlexibleGene(name: String,
131131
}
132132

133133
override fun unsafeCopyValueFrom(other: Gene): Boolean {
134-
if (other !is FlexibleGene)
134+
if (other !is FlexibleGene) {
135135
return false
136-
if (replaceable){
137-
138-
if (!other.isLocallyValid())
139-
return false
140-
141-
try {
142-
geneCheck(other)
143-
}catch (e: Exception){
144-
return false
145-
}
136+
}
146137

138+
if (replaceable){
147139
val replaced = other.gene.copy()
148140
replaced.resetLocalIdRecursively()
149141
replaceGeneTo(replaced)
142+
return true
150143

151-
}else{
144+
} else {
152145
// TODO need to refactor
153146
log.warn("TOCHECK, attempt to copyValueFrom when it is not replaceable")
154147
}

core/src/test/kotlin/org/evomaster/core/search/gene/GeneRandomizedTest.kt

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package org.evomaster.core.search.gene
44
import org.evomaster.core.search.gene.interfaces.WrapperGene
55
import org.evomaster.core.search.service.Randomness
66
import org.junit.jupiter.api.Assertions.assertEquals
7+
import org.junit.jupiter.api.Assertions.assertFalse
78
import org.junit.jupiter.api.Assertions.assertTrue
89
import org.junit.jupiter.api.DynamicTest
910
import org.junit.jupiter.api.TestFactory
@@ -26,26 +27,65 @@ class GeneRandomizedTest : AbstractGeneTest(){
2627
rand.updateSeed(seed)
2728
val sample = getSample(seed)
2829

29-
sample.filter { it.isMutable() }
30-
.forEach { root ->
31-
root.doInitialize(rand)
32-
checkInvariants(root) // all invariants should hold
33-
34-
val copy = root.copy()
35-
checkInvariants(copy) //same for a copy
36-
37-
if(root.isGloballyValid()) { //in these tests, global constraints are not handled
38-
if (root.isPrintable()) {
39-
val x = root.getValueAsRawString()
40-
val y = copy.getValueAsRawString()
41-
assertEquals(x, y) // the copy should result in same phenotype
42-
} else {
43-
assertThrows<Exception>("Should throw exception when trying to print ${root.javaClass}") {
44-
root.getValueAsRawString()
45-
}
46-
}
30+
val mutable = sample.filter { it.isMutable() }
31+
32+
mutable.forEach { root ->
33+
root.doInitialize(rand)
34+
checkInvariants(root) // all invariants should hold
35+
36+
val copy = root.copy()
37+
checkInvariants(copy) //same for a copy
38+
39+
if(root.isGloballyValid()) { //in these tests, global constraints are not handled
40+
if (root.isPrintable()) {
41+
val x = root.getValueAsRawString()
42+
val y = copy.getValueAsRawString()
43+
assertEquals(x, y) // the copy should result in same phenotype
44+
} else {
45+
assertThrows<Exception>("Should throw exception when trying to print ${root.javaClass}") {
46+
root.getValueAsRawString()
4747
}
4848
}
49+
}
50+
}
51+
52+
//FIXME put back once fix all issues it finds
53+
//verifyCopyValueFrom(mutable, rand)
54+
}
55+
56+
private fun verifyCopyValueFrom(
57+
mutable: List<Gene>,
58+
rand: Randomness
59+
) {
60+
val printable = mutable.filter { it.isGloballyValid() && it.isPrintable() }
61+
62+
printable.forEach { root ->
63+
64+
val x = root.copy()
65+
val sx = x.getValueAsRawString()
66+
67+
val y = x.copy().apply { randomize(rand, true) }
68+
val sy = y.getValueAsRawString()
69+
70+
if (sx == sy) {
71+
//randomization did not change phenotype... but might still change the genotype!!!
72+
//rare but this can happen, eg when internal genes in a collection are not printable
73+
//assertTrue(x.containsSameValueAs(y))
74+
} else {
75+
//they must be different. the same genotype must not lead to different phenotypes
76+
assertFalse(x.containsSameValueAs(y))
77+
78+
//with same type and constraints, even "unsafe" should always work
79+
val wasCopied = x.unsafeCopyValueFrom(y)
80+
assertTrue(wasCopied)
81+
82+
assertTrue(x.containsSameValueAs(y))
83+
}
84+
85+
val other = rand.choose(printable)
86+
//this should not crash, ie throw any exception
87+
x.copyValueFrom(other)
88+
}
4989
}
5090

5191

@@ -78,6 +118,9 @@ class GeneRandomizedTest : AbstractGeneTest(){
78118
assertEquals(gene, leaf)
79119
}
80120

121+
//must contain same value as itself
122+
assertTrue(gene.containsSameValueAs(gene))
123+
81124
//TODO add more invariants here
82125
}
83126
}

0 commit comments

Comments
 (0)