I’ve been working on writing unit tests for my implementations of VariantConverters for various juce types, and I think I’ve found a bug in BigInteger’s to/from MemoryBlock functions.
First, here’s what the unit test code looks like:
void runTest() final
{
BigInteger orig { getRandom().nextInt64() };
const auto var = VariantConverter<BigInteger>::toVar (orig);
const auto decoded = VariantConverter<BigInteger>::fromVar (var);
expect (decoded == orig);
}
At first, my VariantConverter<BigInteger>
implementation looked like this:
template <>
struct VariantConverter<BigInteger>
{
static BigInteger fromVar (const var& v)
{
BigInteger i;
if (const auto* block = v.getBinaryData())
i.loadFromMemoryBlock (*block);
return i;
}
static var toVar (const BigInteger& i)
{
return { i.toMemoryBlock() };
}
};
With this implementation, my unit test occasionally succeeded but sometimes spuriously failed; upon inspecting the failure conditions, it seems like the decoded
BigInteger has the same values as the original, but the opposite sign.
So I changed my VariantConverter to this:
template <>
struct VariantConverter<BigInteger>
{
static BigInteger fromVar (const var& v)
{
BigInteger i;
if (const auto* obj = v.getDynamicObject())
{
if (obj->hasProperty (data))
if (const auto* block = obj->getProperty (data).getBinaryData())
i.loadFromMemoryBlock (*block);
if (obj->hasProperty (negative))
i.setNegative ((bool) obj->getProperty (negative));
}
return i;
}
static var toVar (const BigInteger& i)
{
DynamicObject obj;
obj.setProperty (data, i.toMemoryBlock());
obj.setProperty (negative, i.isNegative());
return { obj.clone().get() };
}
private:
static constexpr auto data = "Data";
static constexpr auto negative = "Negative";
};
And now the test succeeds reliably.