Lo tengo. Y sí, es un error.
El problema es que hay dos niveles de string.Format
acción aquí.
El primer nivel de formateo es algo como:
string template = string.Format("Expected: {0}; Actual: {1}; Message: {2}",
expected, actual, message);
Luego usamos string.Format
con los parámetros que ha proporcionado:
string finalMessage = string.Format(template, parameters);
(Obviamente, se están proporcionando cultivos y algún tipo de desinfección ... pero no lo suficiente).
Eso se ve bien, a menos que los valores esperados y reales terminen con llaves, después de convertirse en una cadena, para lo cual sirven Size
. Por ejemplo, su primer tamaño termina convirtiéndose en:
{Width=0, Height=0}
Entonces, el segundo nivel de formato es algo como:
string.Format("Expected: {Width=0, Height=0}; Actual: {Width=1, Height=1 }; " +
"Message = Failed expected {0} actually is {1}", struct1, struct2);
... y eso es lo que falla. Ay.
De hecho, podemos probar esto muy fácilmente engañando al formato para que use nuestros parámetros para las partes esperadas y reales:
var x = "{0}";
var y = "{1}";
Assert.AreEqual<object>(x, y, "What a surprise!", "foo", "bar");
El resultado es:
Assert.AreEqual failed. Expected:<foo>. Actual:<bar>. What a surprise!
Claramente roto, ya que no lo esperábamos foo
ni el valor real bar
.
Básicamente, esto es como un ataque de inyección SQL, pero en el contexto bastante menos aterrador de string.Format
.
Como solución alternativa, puede utilizarlo string.Format
como sugiere StriplingWarrior. Eso evita que se realice el segundo nivel de formateo en el resultado del formateo con los valores reales / esperados.
Assert.AreEqual(struct1, struct2, string.Format("Failed expected {0} actually is {1}
, struct1.ToString (), struct2.ToString ())) `?