Archives for: 2017

16/06/17

Permalink 09:38:52 am, Categories: Technology, Rant, 431 words   English (UK)

Bug in BizTalk LogicalAnd functoid

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.

carbon14 Blog

Everything that's happening in the world of carbon14

2017
<<     >>
Jan Feb Mar Apr
May Jun Jul Aug
Sep Oct Nov Dec

Search

Categories


Linkblog

Friends

Service Providers

Comics

Misc

Syndicate this blog XML

What is RSS?

powered by
b2evolution