While unit testing my own functoids, I came across an odd scenario where my map was working with inline C#, but if I switched to testing the external assembly version, the results were completely different. Obviously I started with the assumption that my functoid was broken, but in fact it appears that it's Microsoft's LogicalAnd functoid which is broken, and has been since BizTalk 2006.
I must stress, that the failure only occurs when you are using the external assembly version of the functoid, which would occur only when you have set the script type preference on your map to give higher priority to the external assembly script type than the inline C# script type. And frankly I still don't know why you would ever want to do that. But if you do, the LogicalAnd functoid is broken.
In BizTalk 2004, the functoid used this code which works:
// Microsoft.BizTalk.BaseFunctoids.FunctoidScripts
public bool LogicalAnd(string val1, string val2)
{
bool flag = false;
try
{
flag = bool.Parse(val1);
}
catch (Exception)
{
if (BaseFunctoid.IsNumeric(val1))
{
int num = Convert.ToInt32(val1, CultureInfo.get_InvariantCulture());
flag = (0 < num);
}
else
{
flag = false;
}
}
if (flag)
{
try
{
bool flag2 = bool.Parse(val2);
flag = (flag && flag2);
}
catch (Exception)
{
if (BaseFunctoid.IsNumeric(val2))
{
int num2 = Convert.ToInt32(val2, CultureInfo.get_InvariantCulture());
bool flag3 = true;
if (0 >= num2)
{
flag3 = false;
}
flag = (flag && flag3);
}
else
{
flag = false;
}
}
}
return flag;
}
but at some point, either in BizTalk 2006 or in 2006r2 they changed to this code:
// Microsoft.BizTalk.BaseFunctoids.FunctoidScripts
public bool LogicalAnd(string val1, string val2)
{
bool flag = false;
if (!bool.TryParse(val1, out flag))
{
if (BaseFunctoid.IsNumeric(val1))
{
int num = Convert.ToInt32(val1, CultureInfo.InvariantCulture);
flag = (0 < num);
}
else
{
flag = false;
}
}
if (flag)
{
bool flag2 = false;
if (!bool.TryParse(val2, out flag2))
{
flag = (flag && flag2);
}
else if (BaseFunctoid.IsNumeric(val2))
{
int num2 = Convert.ToInt32(val2, CultureInfo.InvariantCulture);
flag2 = true;
if (0 >= num2)
{
flag2 = false;
}
flag = (flag && flag2);
}
else
{
flag = false;
}
}
return flag;
}
The new code is cleaner, and uses the TryParse method of the Boolean, presumably to avoid the overhead of the try..catch block. But the sense of the second parse test is the wrong way round; that second exclamation mark shouldn't be there; and as a result this function will almost always return false.
The fact that this bug appears to have survived for a decade suggests that no-one ever chooses to prioritise external assemblies in their maps, but you never know.
A Boolean and function should be the easiest thing to get right, and it certainly shouldn't be difficult to have unit testing this function.
Everything that's happening in the world of carbon14
Mon | Tue | Wed | Thu | Fri | Sat | Sun |
---|---|---|---|---|---|---|
<< < | > >> | |||||
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 |