Don't use more than X MB for this test should work, and even be semi-stable across different test machines and environments (unlike, say, "don't use more than X seconds.") But a true memory leak should be unambiguous. If you can keep doing a thing which should be constant memory, either it is and the utilization is flat, or it isn't and you can watch it creep upward to OOM. I'm not sure what we're thinking of as a leak when it comes to uniques, because it is cleared after every compiler run...
Speaking of uniques, I'd forgotten about this atrocity. This really must go. As usual, I complained at the time.
object ConstantType extends ConstantTypeExtractor {
def apply(value: Constant): ConstantType = {
val tpe = new UniqueConstantType(value)
if (value.tag == ClazzTag) {
// if we carry a classOf, we might be in trouble
// I don't have time for a thorough fix, so I put a hacky workaround here
val alreadyThere = uniques findEntry tpe
if ((alreadyThere ne null) && (alreadyThere ne tpe) && (alreadyThere.toString != tpe.toString)) {
// we need to remove a stale type that has the same hashcode as we do
// HashSet doesn't support removal, and this makes our task non-trivial
// also we cannot simply recreate it, because that'd skew hashcodes (that change over time, omg!)
// the only solution I can see is getting into the underlying array and sneakily manipulating it
val ftable = uniques.getClass.getDeclaredFields().find(f => f.getName endsWith "table").get
ftable.setAccessible(true)
val table = ftable.get(uniques).asInstanceOf[Array[AnyRef]]
def overwrite(hc: Int, x: Type) {
def index(x: Int): Int = math.abs(x % table.length)
var h = index(hc)
var entry = table(h)
while (entry ne null) {
if (x == entry)
table(h) = x
h = index(h + 1)
entry = table(h)
}
}
overwrite(tpe.##, tpe)
}
}
unique(tpe).asInstanceOf[ConstantType]
}
}